/home/cyniu/GIT/WiringPi/wiringPi/wiringPi.h
Line
Count
Source
1
12
#define LOW 0
2
8
#define HIGH 1
3
4
int  digitalRead         (int pin) ;
5
void digitalWrite (int pin, int value) ;
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/ftplibpp/ftplib.h
Line
Count
Source (jump to first uncovered line)
1
/***************************************************************************
2
                          ftplib.h  -  description
3
                             -------------------
4
    begin                : Son Jul 27 2003
5
    copyright            : (C) 2013 by magnus kulke
6
    email                : mkulke@gmail.com
7
 ***************************************************************************/
8
9
/***************************************************************************
10
 *                                                                         *
11
 *   This program is free software; you can redistribute it and/or modify  *
12
 *   it under the terms of the GNU Lesser General Public License as        * 
13
 *   published by the Free Software Foundation; either version 2.1 of the  *
14
 *   License, or (at your option) any later version.                       *
15
 *                                                                         *
16
 ***************************************************************************/
17
 
18
/***************************************************************************
19
 * Note: ftplib, on which ftplibpp was originally based upon used to be    *
20
 * licensed as GPL 2.0 software, as of Jan. 26th 2013 its author Thomas    *
21
 * Pfau allowed the distribution of ftplib via LGPL. Thus the license of   *
22
 * ftplibpp changed aswell.                                                *
23
 ***************************************************************************/
24
 
25
#ifndef FTPLIB_H
26
#define FTPLIB_H
27
28
#if defined(_WIN32)
29
30
#if BUILDING_DLL
31
# define DLLIMPORT __declspec (dllexport)
32
#else /* Not BUILDING_DLL */
33
# define DLLIMPORT __declspec (dllimport)
34
#endif /* Not BUILDING_DLL */
35
36
#include <time.h>
37
#endif
38
39
#ifndef _WIN32
40
#include <unistd.h>
41
#include <sys/time.h>
42
#endif
43
44
#ifdef NOLFS
45
#define off64_t long
46
#endif
47
48
#if defined(__APPLE__)
49
#define off64_t __darwin_off_t
50
#define fseeko64 fseeko
51
#define fopen64 fopen
52
#endif
53
54
#ifndef NOSSL
55
#include <openssl/ssl.h>
56
#endif
57
58
#ifndef _FTPLIB_SSL_CLIENT_METHOD_
59
#define _FTPLIB_SSL_CLIENT_METHOD_ TLSv1_2_client_method
60
#endif//_FTPLIB_SSL_CLIENT_METHOD_
61
62
using namespace std;
63
64
/**
65
  *@author mkulke
66
  */
67
68
typedef int (*FtpCallbackXfer)(off64_t xfered, void *arg);
69
typedef int (*FtpCallbackIdle)(void *arg);
70
typedef void (*FtpCallbackLog)(char *str, void* arg, bool out);
71
72
#ifndef NOSSL
73
typedef bool (*FtpCallbackCert)(void *arg, X509 *cert);
74
#endif
75
76
struct ftphandle {
77
  char *cput,*cget;
78
  int handle;
79
  int cavail,cleft;
80
  char *buf;
81
  int dir;
82
  ftphandle *ctrl;
83
  int cmode;
84
  struct timeval idletime;
85
  FtpCallbackXfer xfercb;
86
  FtpCallbackIdle idlecb;
87
  FtpCallbackLog logcb;
88
  void *cbarg;
89
  off64_t xfered;
90
  off64_t cbbytes;
91
  off64_t xfered1;
92
  char response[256];
93
#ifndef NOSSL
94
  SSL* ssl;
95
  SSL_CTX* ctx;
96
  BIO* sbio;
97
  int tlsctrl;
98
  int tlsdata;
99
  FtpCallbackCert certcb;
100
#endif
101
  off64_t offset;
102
  bool correctpasv;
103
};
104
105
#if defined(_WIN32)  
106
class DLLIMPORT ftplib {
107
#else
108
class ftplib {
109
#endif
110
public:
111
112
  enum accesstype
113
  {
114
    dir = 1,
115
    dirverbose,
116
    fileread,
117
    filewrite,
118
    filereadappend,
119
    filewriteappend
120
  }; 
121
122
  enum transfermode
123
  {
124
    ascii = 'A',
125
    image = 'I'
126
  };
127
128
  enum connmode
129
  {
130
    pasv = 1,
131
    port
132
  };
133
134
  enum fxpmethod
135
  {
136
    defaultfxp = 0,
137
        alternativefxp
138
  };
139
140
    enum dataencryption
141
    {
142
        unencrypted = 0,
143
        secure
144
    };
145
146
  ftplib();
147
  ~ftplib();
148
    char* LastResponse();
149
    int Connect(const char *host);
150
    int Login(const char *user, const char *pass);
151
    int Site(const char *cmd);
152
    int Raw(const char *cmd);
153
    int SysType(char *buf, int max);
154
    int Mkdir(const char *path);
155
    int Chdir(const char *path);
156
    int Cdup();
157
    int Rmdir(const char *path);
158
    int Pwd(char *path, int max);
159
    int Nlst(const char *outputfile, const char *path);
160
    int Dir(const char *outputfile, const char *path);
161
    int Size(const char *path, int *size, transfermode mode);
162
    int ModDate(const char *path, char *dt, int max);
163
    int Get(const char *outputfile, const char *path, transfermode mode, off64_t offset = 0);
164
    int Put(const char *inputfile, const char *path, transfermode mode, off64_t offset = 0);
165
    int Rename(const char *src, const char *dst);
166
    int Delete(const char *path);
167
#ifndef NOSSL    
168
  int SetDataEncryption(dataencryption enc);
169
    int NegotiateEncryption();
170
  void SetCallbackCertFunction(FtpCallbackCert pointer);
171
#endif
172
    int Quit();
173
    void SetCallbackIdleFunction(FtpCallbackIdle pointer);
174
    void SetCallbackLogFunction(FtpCallbackLog pointer);
175
  void SetCallbackXferFunction(FtpCallbackXfer pointer);
176
  void SetCallbackArg(void *arg);
177
    void SetCallbackBytes(off64_t bytes);
178
0
  void SetCorrectPasv(bool b) { mp_ftphandle->correctpasv = b; };
179
    void SetCallbackIdletime(int time);
180
    void SetConnmode(connmode mode);
181
    static int Fxp(ftplib* src, ftplib* dst, const char *pathSrc, const char *pathDst, transfermode mode, fxpmethod method);
182
    
183
  ftphandle* RawOpen(const char *path, accesstype type, transfermode mode);
184
  int RawClose(ftphandle* handle); 
185
  int RawWrite(void* buf, int len, ftphandle* handle);
186
  int RawRead(void* buf, int max, ftphandle* handle); 
187
188
private:
189
    ftphandle* mp_ftphandle;
190
191
    int FtpXfer(const char *localfile, const char *path, ftphandle *nControl, accesstype type, transfermode mode);
192
    int FtpOpenPasv(ftphandle *nControl, ftphandle **nData, transfermode mode, int dir, char *cmd);
193
    int FtpSendCmd(const char *cmd, char expresp, ftphandle *nControl);
194
    int FtpAcceptConnection(ftphandle *nData, ftphandle *nControl);
195
    int FtpOpenPort(ftphandle *nControl, ftphandle **nData, transfermode mode, int dir, char *cmd);
196
    int FtpRead(void *buf, int max, ftphandle *nData);
197
    int FtpWrite(void *buf, int len, ftphandle *nData);
198
    int FtpAccess(const char *path, accesstype type, transfermode mode, ftphandle *nControl, ftphandle **nData);
199
    int FtpClose(ftphandle *nData);
200
  
201
  int socket_wait(ftphandle *ctl);
202
    int readline(char *buf,int max,ftphandle *ctl);
203
    int writeline(char *buf, int len, ftphandle *nData);
204
    int readresp(char c, ftphandle *nControl);
205
  
206
  void ClearHandle();
207
  int CorrectPasvResponse(unsigned char *v);
208
};
209
210
#endif
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/libs/Statistic/statistic.h
Line
Count
Source
1
#ifndef STATISTIC_H
2
#define STATISTIC_H
3
#include <iostream>
4
#include <deque>
5
#include <numeric>
6
#include <algorithm>
7
#include <sstream>
8
#include <cmath>
9
#include <vector>
10
11
template <class T>
12
class STATISTIC
13
{
14
public:
15
    STATISTIC(unsigned int size): m_size(size)
16
801
    {
17
801
18
801
    }
19
3
    void resize(unsigned int i){
20
3
        if (i < m_size){
21
24
            while(m_dequeue.size()> i){
22
21
                pop_front();
23
21
            }
24
3
        }
25
3
        m_size = i;
26
3
    }
27
79
    T size(){
28
79
        return  static_cast<T>(m_dequeue.size());
29
79
    }
30
10
    void push_front(T v){
31
10
        if (m_dequeue.size() >= m_size){
32
1
            pop_back();
33
1
        }
34
10
        m_dequeue.push_front(v);
35
10
    }
36
307
    void push_back(T v){
37
307
        if (m_dequeue.size() >= m_size){
38
2
            pop_front();
39
2
        }
40
307
        m_dequeue.push_back(v);
41
307
    }
42
3
    void pop_back(){
43
3
        m_dequeue.pop_back();
44
3
        // std::cout <<"pop_back"<<std::endl;
45
3
    }
46
23
    void pop_front(){
47
23
        m_dequeue.pop_front();
48
23
        // std::cout <<"pop_front"<<std::endl;
49
23
    }
50
    ///////////////////////////////////////////// statistic /////////////////////////////
51
5
    T median(){
52
5
        auto backup = m_dequeue;
53
5
        std::sort(backup.begin(), backup.end());
54
5
        if (backup.size() % 2 != 0){
55
3
            return backup[backup.size() / 2];
56
3
        }
57
5
        else{
58
2
            T m = backup[backup.size() / 2] + backup[(backup.size() / 2)-1];
59
2
            return m /2;
60
2
        }
61
5
    }
62
23
    T sum(){
63
23
        return std::accumulate(m_dequeue.begin(), m_dequeue.end(), static_cast<T>(0));
64
23
    }
65
66
23
    T average(){
67
23
        T av  = sum() /size();
68
23
        return av;
69
23
    }
70
71
5
    T max(){
72
5
        T max = m_dequeue[0];
73
40
        for (auto v : m_dequeue){
74
40
            if (v > max){
75
13
                max = v;
76
13
            }
77
40
        }
78
5
        return max;
79
5
    }
80
81
5
    T min(){
82
5
        T min = m_dequeue[0];
83
40
        for (auto v : m_dequeue){
84
40
            if (v < min){
85
3
                min = v;
86
3
            }
87
40
        }
88
5
        return min;
89
5
    }
90
91
1
    T range(){
92
1
        return max() - min();
93
1
    }
94
95
6
    T standardDeviation(){
96
6
        double standardDeviation = 0.0;
97
6
        T _av = average();
98
6
99
38
        for(int i = 0; i < size(); ++i){
100
32
            standardDeviation += pow(m_dequeue.at(i) - _av, 2);
101
32
        }
102
6
        return sqrt(standardDeviation / size());
103
6
    }
104
105
3
    T coefficientOfVariation(){
106
3
107
3
        return (standardDeviation()/average()) /** 100*/;
108
3
    }
109
110
13
    T mode(){
111
13
112
13
        T _mode = 0;
113
13
        T _modeTemp = 0;
114
13
        int counter = 1;
115
13
        int modeCounter = 1;
116
13
        auto backup = m_dequeue;
117
13
        if(m_dequeue.size() == 1)
118
13
        {
119
3
            return m_dequeue.at(0);
120
3
        }
121
13
        std::sort(backup.begin(), backup.end());
122
10
#ifdef BT_TEST
123
10
        std::cout << " " << std::endl;
124
10
        for (auto i : backup)
125
89
        {
126
89
            std::cout << i << " ";
127
89
        }
128
10
        std::cout << " " << std::endl;
129
10
#endif
130
10
        _mode = _modeTemp = backup.at(0);
131
10
        backup.pop_front();
132
10
        for (auto b : backup)
133
79
        {
134
79
            if (_modeTemp == b)
135
79
            {
136
15
                modeCounter++;
137
15
            }
138
79
            else
139
79
            {
140
64
                _modeTemp = b;
141
64
                modeCounter = 1;
142
64
            }
143
79
144
79
            if(counter < modeCounter)
145
79
            {
146
8
                counter = modeCounter;
147
8
                _mode = _modeTemp;
148
8
            }
149
79
        }
150
10
#ifdef BT_TEST
151
10
        std::cout << " moda: " << _mode << " wystepuje razy " << counter << std::endl;
152
10
#endif
153
10
        return _mode;
154
13
    }
155
156
    float trend(){
157
        int down = 0;
158
        int eq = 0;
159
        int up = 0;
160
        int lp = 0;
161
        T diff = 0;
162
        T first = m_dequeue[0];
163
164
        for (auto i = 1; i < m_dequeue.size(); ++i){
165
            if (first < m_dequeue[i]){
166
                up++;
167
                if (m_dequeue[i] - first > diff){
168
                    diff = m_dequeue[i] - first;
169
                    lp = i;
170
                }
171
            }
172
            if (first == m_dequeue[i]){ eq++;}
173
            if (first > m_dequeue[i]){
174
                if (diff < first - m_dequeue[i] ){
175
                    diff = first - m_dequeue[i];
176
                    lp = i;
177
                }
178
                down++;
179
            }
180
            first = m_dequeue[i];
181
        }
182
        std::cout <<"up "<<up<<" eq "<< eq << " down "<< down <<" max diff "<< diff<<" lp "<<lp << std::endl;
183
        return 2.2;
184
    }
185
186
20
    bool isMoreDiff(T diff){
187
20
        if (m_dequeue.size()>2){
188
14
            T d = m_dequeue.at( m_dequeue.size()-2)
189
14
                    - m_dequeue.at( m_dequeue.size() - 1);
190
14
            d = fabs(d);
191
14
            if (d > diff && m_alarm == false){
192
6
                m_alarm = true;
193
6
                return true;
194
6
            }
195
14
            if (d <= diff){
196
8
                m_alarm = false;
197
8
                return false;
198
8
            }
199
8
        }
200
20
        return false;
201
20
    }
202
7
    std::pair<double,double> getLast2(){
203
7
        if (m_dequeue.size()>2){
204
6
            return std::make_pair(static_cast<double>(m_dequeue.at( m_dequeue.size()-2)),
205
6
                                  static_cast<double>(m_dequeue.at( m_dequeue.size()-1))    );
206
6
        }
207
7
#ifdef BT_TEST
208
7
        puts("no data - return 0.0 0.0");
209
1
#endif
210
1
        return std::make_pair(0.0,0.0);
211
7
    }
212
213
    /////////////////////////////////////////////////////////////////////////////////////
214
14
    void print(){
215
71
        for(auto n : m_dequeue){
216
71
            std::cout << ","<< n;
217
71
        }
218
14
        std::cout << " " <<std::endl;
219
14
    }
220
221
222
4
    std::string stats(){
223
4
224
4
        std::stringstream ss(" brak danych =(");
225
4
        if(size()>0)
226
4
        {
227
3
            ss.str("");
228
3
            ss <<"rozmiar tablicy: "<< size() <<std::endl
229
3
              << "min: "<< min() <<std::endl
230
3
              << "max: "<< max()<<std::endl
231
3
              << "srednia " << average() <<std::endl
232
3
              << "mediana " << median()  <<std::endl
233
3
              << "odchylenie st "<< standardDeviation() << std::endl
234
3
              << "wspolczynnik zmiennosci " << coefficientOfVariation() <<"%"<< std::endl
235
3
              << "Dominanta " << mode();
236
3
237
3
238
3
            ss << std::endl
239
3
               << "data " <<  std::endl;
240
16
            for(auto n : m_dequeue){
241
16
                ss << "|"<< n;
242
16
            }
243
3
        }
244
4
        ss <<  std::endl;
245
4
        return ss.str();
246
4
    }
247
248
private:
249
    unsigned int m_size;
250
    std::deque <T> m_dequeue;
251
    bool m_alarm = false;
252
};
253
254
#endif // STATISTIC_H
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/libs/Statistic/statistic.h
Line
Count
Source
1
#ifndef STATISTIC_H
2
#define STATISTIC_H
3
#include <iostream>
4
#include <deque>
5
#include <numeric>
6
#include <algorithm>
7
#include <sstream>
8
#include <cmath>
9
#include <vector>
10
11
template <class T>
12
class STATISTIC
13
{
14
public:
15
    STATISTIC(unsigned int size): m_size(size)
16
817
    {
17
817
18
817
    }
_ZN9STATISTICIdEC2Ej
Line
Count
Source
16
801
    {
17
801
18
801
    }
_ZN9STATISTICIiEC2Ej
Line
Count
Source
16
16
    {
17
16
18
16
    }
19
3
    void resize(unsigned int i){
20
3
        if (i < m_size){
21
24
            while(m_dequeue.size()> i){
22
21
                pop_front();
23
21
            }
24
3
        }
25
3
        m_size = i;
26
3
    }
27
79
    T size(){
28
79
        return  static_cast<T>(m_dequeue.size());
29
79
    }
30
10
    void push_front(T v){
31
10
        if (m_dequeue.size() >= m_size){
32
1
            pop_back();
33
1
        }
34
10
        m_dequeue.push_front(v);
35
10
    }
36
599
    void push_back(T v){
37
599
        if (m_dequeue.size() >= m_size){
38
2
            pop_front();
39
2
        }
40
599
        m_dequeue.push_back(v);
41
599
    }
_ZN9STATISTICIdE9push_backEd
Line
Count
Source
36
307
    void push_back(T v){
37
307
        if (m_dequeue.size() >= m_size){
38
2
            pop_front();
39
2
        }
40
307
        m_dequeue.push_back(v);
41
307
    }
_ZN9STATISTICIiE9push_backEi
Line
Count
Source
36
292
    void push_back(T v){
37
292
        if (m_dequeue.size() >= m_size){
38
0
            pop_front();
39
0
        }
40
292
        m_dequeue.push_back(v);
41
292
    }
42
3
    void pop_back(){
43
3
        m_dequeue.pop_back();
44
3
        // std::cout <<"pop_back"<<std::endl;
45
3
    }
46
23
    void pop_front(){
47
23
        m_dequeue.pop_front();
48
23
        // std::cout <<"pop_front"<<std::endl;
49
23
    }
_ZN9STATISTICIdE9pop_frontEv
Line
Count
Source
46
23
    void pop_front(){
47
23
        m_dequeue.pop_front();
48
23
        // std::cout <<"pop_front"<<std::endl;
49
23
    }
Unexecuted instantiation: _ZN9STATISTICIiE9pop_frontEv
50
    ///////////////////////////////////////////// statistic /////////////////////////////
51
13
    T median(){
52
13
        auto backup = m_dequeue;
53
13
        std::sort(backup.begin(), backup.end());
54
13
        if (backup.size() % 2 != 0){
55
5
            return backup[backup.size() / 2];
56
5
        }
57
8
        else{
58
8
            T m = backup[backup.size() / 2] + backup[(backup.size() / 2)-1];
59
8
            return m /2;
60
8
        }
61
13
    }
_ZN9STATISTICIdE6medianEv
Line
Count
Source
51
5
    T median(){
52
5
        auto backup = m_dequeue;
53
5
        std::sort(backup.begin(), backup.end());
54
5
        if (backup.size() % 2 != 0){
55
3
            return backup[backup.size() / 2];
56
3
        }
57
2
        else{
58
2
            T m = backup[backup.size() / 2] + backup[(backup.size() / 2)-1];
59
2
            return m /2;
60
2
        }
61
5
    }
_ZN9STATISTICIiE6medianEv
Line
Count
Source
51
8
    T median(){
52
8
        auto backup = m_dequeue;
53
8
        std::sort(backup.begin(), backup.end());
54
8
        if (backup.size() % 2 != 0){
55
2
            return backup[backup.size() / 2];
56
2
        }
57
6
        else{
58
6
            T m = backup[backup.size() / 2] + backup[(backup.size() / 2)-1];
59
6
            return m /2;
60
6
        }
61
8
    }
62
23
    T sum(){
63
23
        return std::accumulate(m_dequeue.begin(), m_dequeue.end(), static_cast<T>(0));
64
23
    }
65
66
23
    T average(){
67
23
        T av  = sum() /size();
68
23
        return av;
69
23
    }
70
71
5
    T max(){
72
5
        T max = m_dequeue[0];
73
40
        for (auto v : m_dequeue){
74
40
            if (v > max){
75
13
                max = v;
76
13
            }
77
40
        }
78
5
        return max;
79
5
    }
80
81
5
    T min(){
82
5
        T min = m_dequeue[0];
83
40
        for (auto v : m_dequeue){
84
40
            if (v < min){
85
3
                min = v;
86
3
            }
87
40
        }
88
5
        return min;
89
5
    }
90
91
1
    T range(){
92
1
        return max() - min();
93
1
    }
94
95
6
    T standardDeviation(){
96
6
        double standardDeviation = 0.0;
97
6
        T _av = average();
98
6
99
38
        for(int i = 0; i < size(); ++i){
100
32
            standardDeviation += pow(m_dequeue.at(i) - _av, 2);
101
32
        }
102
6
        return sqrt(standardDeviation / size());
103
6
    }
104
105
3
    T coefficientOfVariation(){
106
3
107
3
        return (standardDeviation()/average()) /** 100*/;
108
3
    }
109
110
21
    T mode(){
111
21
112
21
        T _mode = 0;
113
21
        T _modeTemp = 0;
114
21
        int counter = 1;
115
21
        int modeCounter = 1;
116
21
        auto backup = m_dequeue;
117
21
        if(m_dequeue.size() == 1)
118
5
        {
119
5
            return m_dequeue.at(0);
120
5
        }
121
16
        std::sort(backup.begin(), backup.end());
122
16
#ifdef BT_TEST
123
16
        std::cout << " " << std::endl;
124
16
        for (auto i : backup)
125
233
        {
126
233
            std::cout << i << " ";
127
233
        }
128
16
        std::cout << " " << std::endl;
129
16
#endif
130
16
        _mode = _modeTemp = backup.at(0);
131
16
        backup.pop_front();
132
16
        for (auto b : backup)
133
217
        {
134
217
            if (_modeTemp == b)
135
135
            {
136
135
                modeCounter++;
137
135
            }
138
82
            else
139
82
            {
140
82
                _modeTemp = b;
141
82
                modeCounter = 1;
142
82
            }
143
217
144
217
            if(counter < modeCounter)
145
80
            {
146
80
                counter = modeCounter;
147
80
                _mode = _modeTemp;
148
80
            }
149
217
        }
150
16
#ifdef BT_TEST
151
16
        std::cout << " moda: " << _mode << " wystepuje razy " << counter << std::endl;
152
16
#endif
153
16
        return _mode;
154
16
    }
_ZN9STATISTICIdE4modeEv
Line
Count
Source
110
13
    T mode(){
111
13
112
13
        T _mode = 0;
113
13
        T _modeTemp = 0;
114
13
        int counter = 1;
115
13
        int modeCounter = 1;
116
13
        auto backup = m_dequeue;
117
13
        if(m_dequeue.size() == 1)
118
3
        {
119
3
            return m_dequeue.at(0);
120
3
        }
121
10
        std::sort(backup.begin(), backup.end());
122
10
#ifdef BT_TEST
123
10
        std::cout << " " << std::endl;
124
10
        for (auto i : backup)
125
89
        {
126
89
            std::cout << i << " ";
127
89
        }
128
10
        std::cout << " " << std::endl;
129
10
#endif
130
10
        _mode = _modeTemp = backup.at(0);
131
10
        backup.pop_front();
132
10
        for (auto b : backup)
133
79
        {
134
79
            if (_modeTemp == b)
135
15
            {
136
15
                modeCounter++;
137
15
            }
138
64
            else
139
64
            {
140
64
                _modeTemp = b;
141
64
                modeCounter = 1;
142
64
            }
143
79
144
79
            if(counter < modeCounter)
145
8
            {
146
8
                counter = modeCounter;
147
8
                _mode = _modeTemp;
148
8
            }
149
79
        }
150
10
#ifdef BT_TEST
151
10
        std::cout << " moda: " << _mode << " wystepuje razy " << counter << std::endl;
152
10
#endif
153
10
        return _mode;
154
10
    }
_ZN9STATISTICIiE4modeEv
Line
Count
Source
110
8
    T mode(){
111
8
112
8
        T _mode = 0;
113
8
        T _modeTemp = 0;
114
8
        int counter = 1;
115
8
        int modeCounter = 1;
116
8
        auto backup = m_dequeue;
117
8
        if(m_dequeue.size() == 1)
118
2
        {
119
2
            return m_dequeue.at(0);
120
2
        }
121
6
        std::sort(backup.begin(), backup.end());
122
6
#ifdef BT_TEST
123
6
        std::cout << " " << std::endl;
124
6
        for (auto i : backup)
125
144
        {
126
144
            std::cout << i << " ";
127
144
        }
128
6
        std::cout << " " << std::endl;
129
6
#endif
130
6
        _mode = _modeTemp = backup.at(0);
131
6
        backup.pop_front();
132
6
        for (auto b : backup)
133
138
        {
134
138
            if (_modeTemp == b)
135
120
            {
136
120
                modeCounter++;
137
120
            }
138
18
            else
139
18
            {
140
18
                _modeTemp = b;
141
18
                modeCounter = 1;
142
18
            }
143
138
144
138
            if(counter < modeCounter)
145
72
            {
146
72
                counter = modeCounter;
147
72
                _mode = _modeTemp;
148
72
            }
149
138
        }
150
6
#ifdef BT_TEST
151
6
        std::cout << " moda: " << _mode << " wystepuje razy " << counter << std::endl;
152
6
#endif
153
6
        return _mode;
154
6
    }
155
156
    float trend(){
157
        int down = 0;
158
        int eq = 0;
159
        int up = 0;
160
        int lp = 0;
161
        T diff = 0;
162
        T first = m_dequeue[0];
163
164
        for (auto i = 1; i < m_dequeue.size(); ++i){
165
            if (first < m_dequeue[i]){
166
                up++;
167
                if (m_dequeue[i] - first > diff){
168
                    diff = m_dequeue[i] - first;
169
                    lp = i;
170
                }
171
            }
172
            if (first == m_dequeue[i]){ eq++;}
173
            if (first > m_dequeue[i]){
174
                if (diff < first - m_dequeue[i] ){
175
                    diff = first - m_dequeue[i];
176
                    lp = i;
177
                }
178
                down++;
179
            }
180
            first = m_dequeue[i];
181
        }
182
        std::cout <<"up "<<up<<" eq "<< eq << " down "<< down <<" max diff "<< diff<<" lp "<<lp << std::endl;
183
        return 2.2;
184
    }
185
186
20
    bool isMoreDiff(T diff){
187
20
        if (m_dequeue.size()>2){
188
14
            T d = m_dequeue.at( m_dequeue.size()-2)
189
14
                    - m_dequeue.at( m_dequeue.size() - 1);
190
14
            d = fabs(d);
191
14
            if (d > diff && m_alarm == false){
192
6
                m_alarm = true;
193
6
                return true;
194
6
            }
195
8
            if (d <= diff){
196
8
                m_alarm = false;
197
8
                return false;
198
8
            }
199
6
        }
200
6
        return false;
201
6
    }
202
7
    std::pair<double,double> getLast2(){
203
7
        if (m_dequeue.size()>2){
204
6
            return std::make_pair(static_cast<double>(m_dequeue.at( m_dequeue.size()-2)),
205
6
                                  static_cast<double>(m_dequeue.at( m_dequeue.size()-1))    );
206
6
        }
207
1
#ifdef BT_TEST
208
1
        puts("no data - return 0.0 0.0");
209
1
#endif
210
1
        return std::make_pair(0.0,0.0);
211
1
    }
212
213
    /////////////////////////////////////////////////////////////////////////////////////
214
14
    void print(){
215
71
        for(auto n : m_dequeue){
216
71
            std::cout << ","<< n;
217
71
        }
218
14
        std::cout << " " <<std::endl;
219
14
    }
220
221
222
4
    std::string stats(){
223
4
224
4
        std::stringstream ss(" brak danych =(");
225
4
        if(size()>0)
226
3
        {
227
3
            ss.str("");
228
3
            ss <<"rozmiar tablicy: "<< size() <<std::endl
229
3
              << "min: "<< min() <<std::endl
230
3
              << "max: "<< max()<<std::endl
231
3
              << "srednia " << average() <<std::endl
232
3
              << "mediana " << median()  <<std::endl
233
3
              << "odchylenie st "<< standardDeviation() << std::endl
234
3
              << "wspolczynnik zmiennosci " << coefficientOfVariation() <<"%"<< std::endl
235
3
              << "Dominanta " << mode();
236
3
237
3
238
3
            ss << std::endl
239
3
               << "data " <<  std::endl;
240
16
            for(auto n : m_dequeue){
241
16
                ss << "|"<< n;
242
16
            }
243
3
        }
244
4
        ss <<  std::endl;
245
4
        return ss.str();
246
4
    }
247
248
private:
249
    unsigned int m_size;
250
    std::deque <T> m_dequeue;
251
    bool m_alarm = false;
252
};
253
254
#endif // STATISTIC_H
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/libs/Statistic/statistic_test/statistic_BT.cpp
Line
Count
Source
1
#include <gtest/gtest.h>
2
#include <gmock/gmock.h>
3
#include "../statistic.h"
4
5
class StatisticClass_fixture : public ::testing::Test
6
{
7
public:
8
    STATISTIC<double> average;
9
    StatisticClass_fixture(): average(12)
10
7
    {
11
7
    }
12
    void SetUp() final
13
7
    {
14
7
        average.push_back(1);
15
7
        average.push_back(1);
16
7
        average.push_back(2);
17
7
        average.push_back(2);
18
7
        average.push_back(3);
19
7
        average.push_back(3);
20
7
        average.push_back(4);
21
7
        average.push_back(4);
22
7
        average.push_back(-5);
23
7
        average.push_back(-5);
24
7
        average.push_back(6);
25
7
        average.push_back(6);
26
7
    }
27
    void TearDown() final
28
7
    {
29
7
30
7
    }
31
};
32
33
TEST_F(StatisticClass_fixture, range)
34
1
{
35
1
    EXPECT_DOUBLE_EQ(average.average() , 1.8333333333333333);
36
1
    EXPECT_EQ(average.range(), 11);
37
1
}
38
39
TEST_F(StatisticClass_fixture, average)
40
1
{
41
1
    EXPECT_DOUBLE_EQ(average.average() , 1.8333333333333333);
42
1
    std::string ret = average.stats();
43
1
    EXPECT_THAT(ret, testing::HasSubstr("max"));
44
1
}
45
TEST_F(StatisticClass_fixture, averageOne)
46
1
{
47
1
    average.resize(1);
48
1
    average.push_back(1);
49
1
    EXPECT_DOUBLE_EQ(average.average() , 1.0);
50
1
}
51
TEST_F(StatisticClass_fixture, median)
52
1
{
53
1
    EXPECT_EQ(average.median(),2.5f);
54
1
}
55
TEST(StatisticClass, medianOne)
56
1
{
57
1
    STATISTIC<double> average(1);
58
1
    average.push_back(1);
59
1
    EXPECT_EQ(average.median(), 1.0f);
60
1
}
61
TEST_F(StatisticClass_fixture, min)
62
1
{
63
1
    EXPECT_EQ(average.min(),-5.0f);
64
1
}
65
TEST_F(StatisticClass_fixture, max)
66
1
{
67
1
    EXPECT_EQ(average.max(),6);
68
1
}
69
TEST_F(StatisticClass_fixture, push_and_pop)
70
1
{
71
1
    average.pop_back();
72
1
    EXPECT_EQ(average.size(),11);
73
1
    average.push_front(3.9);
74
1
    EXPECT_EQ(average.size(),12);
75
1
    average.pop_back();
76
1
    EXPECT_EQ(average.size(),11);
77
1
}
78
79
TEST(StatisticClass, resize)
80
1
{
81
1
    unsigned int s = 3;
82
1
    STATISTIC<double> average(12);
83
1
    average.push_back(1);
84
1
    average.push_back(2);
85
1
    average.push_back(3);
86
1
    average.push_back(4);
87
1
    average.push_back(5);
88
1
    average.push_front(44);
89
1
    average.push_front(45);
90
1
    average.print();
91
1
    average.resize(s);
92
1
93
1
    EXPECT_EQ(average.size(),static_cast<double>(s));
94
1
95
1
    auto data = average.getLast2();
96
1
    average.print();
97
1
98
1
    EXPECT_EQ(data.first,4.0);
99
1
    EXPECT_EQ(data.second,5.0);
100
1
}
101
102
TEST(StatisticClass, getLast2_empty)
103
1
{
104
1
    unsigned int s = 1;
105
1
    STATISTIC<double> average(12);
106
1
    average.push_back(1);
107
1
    average.push_back(2);
108
1
    average.push_back(3);
109
1
    average.push_back(4);
110
1
    average.push_back(5);
111
1
    average.push_front(44);
112
1
    average.push_front(45);
113
1
    average.print();
114
1
    average.resize(s);
115
1
    average.push_front(33);
116
1
117
1
    EXPECT_EQ(average.size(),static_cast<double>(s));
118
1
119
1
    auto data = average.getLast2();
120
1
    average.print();
121
1
122
1
    EXPECT_EQ(data.first,0.0);
123
1
    EXPECT_EQ(data.second,0.0);
124
1
}
125
126
TEST(StatisticClass, moreDiff)
127
1
{
128
1
    STATISTIC<double> average(12);
129
1
    average.push_back(1);
130
1
    average.push_back(2);
131
1
    average.push_back(30);
132
1
    average.push_back(4);
133
1
    average.push_back(5);
134
1
    average.push_front(44);
135
1
    average.push_front(45);
136
1
    average.print();
137
1
138
1
    EXPECT_FALSE(average.isMoreDiff(2.2));
139
1
140
1
    average.push_back(7.3);
141
1
    average.print();
142
1
143
1
    EXPECT_TRUE(average.isMoreDiff(2.2));
144
1
}
145
146
TEST(StatisticClass, moreDiff_wrong)
147
1
{
148
1
    STATISTIC<double> average(1);
149
1
    average.push_back(1);
150
1
151
1
    average.print();
152
1
153
1
    EXPECT_FALSE(average.isMoreDiff(2.2));
154
1
155
1
    average.push_back(7.3);
156
1
    average.print();
157
1
158
1
    EXPECT_FALSE(average.isMoreDiff(2.2));
159
1
}
160
161
TEST(StatisticClass, noMoreDiff)
162
1
{
163
1
    STATISTIC<double> average(12);
164
1
    average.push_back(1);
165
1
    average.push_back(2);
166
1
    average.push_back(30);
167
1
    average.push_back(4);
168
1
    average.push_back(5);
169
1
    average.push_front(44);
170
1
    average.push_front(45);
171
1
    average.print();
172
1
173
1
    EXPECT_FALSE(average.isMoreDiff(6.2));
174
1
175
1
    average.push_back(7.3);
176
1
    average.print();
177
1
178
1
    EXPECT_FALSE(average.isMoreDiff(9.2));
179
1
}
180
181
TEST(StatisticClass, mode)
182
1
{
183
1
    STATISTIC<double> average(22);
184
1
    average.push_back(29.62);
185
1
    average.push_back(29.71);
186
1
    average.push_back(30.19);
187
1
    average.push_back(33.5);
188
1
    average.push_back(30.31);
189
1
    average.push_back(30.81);
190
1
    average.push_back(30.87);
191
1
    average.push_back(31.25);
192
1
    average.push_back(31.31);
193
1
    average.push_back(31.56);
194
1
    average.push_back(31.87);
195
1
    average.push_back(31.94);
196
1
    average.push_back(32.13);
197
1
    average.push_back(32.13);  //to
198
1
    average.push_back(32.63);
199
1
200
1
    average.print();
201
1
    std::cout << "1 MODE: " << average.mode() << std::endl;
202
3
    EXPECT_DOUBLE_EQ(32.13,average.mode()) << "ZLA DOMINANTA 32.13";
203
1
    average.push_back(33.5);
204
1
    average.push_back(33.5);
205
1
    std::cout << "2 MODE: " << average.mode() << std::endl;
206
3
    EXPECT_DOUBLE_EQ(33.5,average.mode()) << "ZLA DOMINANTA 33.5";
207
1
}
208
TEST(StatisticClass, modeOne)
209
1
{
210
1
    STATISTIC<double> average(1);
211
1
    average.push_back(29.62);
212
1
    average.print();
213
1
    std::cout << "1 MODE: " << average.mode() << std::endl;
214
3
    EXPECT_DOUBLE_EQ(29.62,average.mode()) << "ZLA DOMINANTA 32.13";
215
1
}
216
TEST(StatisticClass, modeTwo)
217
1
{
218
1
    STATISTIC<double> average(10);
219
1
    average.push_back(29.62);
220
1
    average.push_back(28.62);
221
1
    average.print();
222
1
    std::cout << "1 MODE: " << average.mode() << std::endl;
223
3
    EXPECT_DOUBLE_EQ(28.62,average.mode()) << "ZLA DOMINANTA 32.13";
224
1
}
225
TEST(StatisticClass, modeThree)
226
1
{
227
1
    STATISTIC<double> average(10);
228
1
    average.push_back(29.62);
229
1
    average.push_back(28.62);
230
1
    average.push_back(29.63);
231
1
    average.print();
232
1
    std::cout << "1 MODE: " << average.mode() << std::endl;
233
3
    EXPECT_DOUBLE_EQ(28.62,average.mode()) << "ZLA DOMINANTA 32.13";
234
1
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/libs/Statistic/statistic_test/statistic_BT.cpp
Line
Count
Source
1
#include <gtest/gtest.h>
2
#include <gmock/gmock.h>
3
#include "../statistic.h"
4
5
class StatisticClass_fixture : public ::testing::Test
6
{
7
public:
8
    STATISTIC<double> average;
9
    StatisticClass_fixture(): average(12)
10
7
    {
11
7
    }
12
    void SetUp() final
13
7
    {
14
7
        average.push_back(1);
15
7
        average.push_back(1);
16
7
        average.push_back(2);
17
7
        average.push_back(2);
18
7
        average.push_back(3);
19
7
        average.push_back(3);
20
7
        average.push_back(4);
21
7
        average.push_back(4);
22
7
        average.push_back(-5);
23
7
        average.push_back(-5);
24
7
        average.push_back(6);
25
7
        average.push_back(6);
26
7
    }
27
    void TearDown() final
28
7
    {
29
7
30
7
    }
31
};
32
33
TEST_F(StatisticClass_fixture, range)
34
1
{
35
1
    EXPECT_DOUBLE_EQ(average.average() , 1.8333333333333333);
36
1
    EXPECT_EQ(average.range(), 11);
37
1
}
38
39
TEST_F(StatisticClass_fixture, average)
40
1
{
41
1
    EXPECT_DOUBLE_EQ(average.average() , 1.8333333333333333);
42
1
    std::string ret = average.stats();
43
1
    EXPECT_THAT(ret, testing::HasSubstr("max"));
44
1
}
45
TEST_F(StatisticClass_fixture, averageOne)
46
1
{
47
1
    average.resize(1);
48
1
    average.push_back(1);
49
1
    EXPECT_DOUBLE_EQ(average.average() , 1.0);
50
1
}
51
TEST_F(StatisticClass_fixture, median)
52
1
{
53
1
    EXPECT_EQ(average.median(),2.5f);
54
1
}
55
TEST(StatisticClass, medianOne)
56
1
{
57
1
    STATISTIC<double> average(1);
58
1
    average.push_back(1);
59
1
    EXPECT_EQ(average.median(), 1.0f);
60
1
}
61
TEST_F(StatisticClass_fixture, min)
62
1
{
63
1
    EXPECT_EQ(average.min(),-5.0f);
64
1
}
65
TEST_F(StatisticClass_fixture, max)
66
1
{
67
1
    EXPECT_EQ(average.max(),6);
68
1
}
69
TEST_F(StatisticClass_fixture, push_and_pop)
70
1
{
71
1
    average.pop_back();
72
1
    EXPECT_EQ(average.size(),11);
73
1
    average.push_front(3.9);
74
1
    EXPECT_EQ(average.size(),12);
75
1
    average.pop_back();
76
1
    EXPECT_EQ(average.size(),11);
77
1
}
78
79
TEST(StatisticClass, resize)
80
1
{
81
1
    unsigned int s = 3;
82
1
    STATISTIC<double> average(12);
83
1
    average.push_back(1);
84
1
    average.push_back(2);
85
1
    average.push_back(3);
86
1
    average.push_back(4);
87
1
    average.push_back(5);
88
1
    average.push_front(44);
89
1
    average.push_front(45);
90
1
    average.print();
91
1
    average.resize(s);
92
1
93
1
    EXPECT_EQ(average.size(),static_cast<double>(s));
94
1
95
1
    auto data = average.getLast2();
96
1
    average.print();
97
1
98
1
    EXPECT_EQ(data.first,4.0);
99
1
    EXPECT_EQ(data.second,5.0);
100
1
}
101
102
TEST(StatisticClass, getLast2_empty)
103
1
{
104
1
    unsigned int s = 1;
105
1
    STATISTIC<double> average(12);
106
1
    average.push_back(1);
107
1
    average.push_back(2);
108
1
    average.push_back(3);
109
1
    average.push_back(4);
110
1
    average.push_back(5);
111
1
    average.push_front(44);
112
1
    average.push_front(45);
113
1
    average.print();
114
1
    average.resize(s);
115
1
    average.push_front(33);
116
1
117
1
    EXPECT_EQ(average.size(),static_cast<double>(s));
118
1
119
1
    auto data = average.getLast2();
120
1
    average.print();
121
1
122
1
    EXPECT_EQ(data.first,0.0);
123
1
    EXPECT_EQ(data.second,0.0);
124
1
}
125
126
TEST(StatisticClass, moreDiff)
127
1
{
128
1
    STATISTIC<double> average(12);
129
1
    average.push_back(1);
130
1
    average.push_back(2);
131
1
    average.push_back(30);
132
1
    average.push_back(4);
133
1
    average.push_back(5);
134
1
    average.push_front(44);
135
1
    average.push_front(45);
136
1
    average.print();
137
1
138
1
    EXPECT_FALSE(average.isMoreDiff(2.2));
139
1
140
1
    average.push_back(7.3);
141
1
    average.print();
142
1
143
1
    EXPECT_TRUE(average.isMoreDiff(2.2));
144
1
}
145
146
TEST(StatisticClass, moreDiff_wrong)
147
1
{
148
1
    STATISTIC<double> average(1);
149
1
    average.push_back(1);
150
1
151
1
    average.print();
152
1
153
1
    EXPECT_FALSE(average.isMoreDiff(2.2));
154
1
155
1
    average.push_back(7.3);
156
1
    average.print();
157
1
158
1
    EXPECT_FALSE(average.isMoreDiff(2.2));
159
1
}
160
161
TEST(StatisticClass, noMoreDiff)
162
1
{
163
1
    STATISTIC<double> average(12);
164
1
    average.push_back(1);
165
1
    average.push_back(2);
166
1
    average.push_back(30);
167
1
    average.push_back(4);
168
1
    average.push_back(5);
169
1
    average.push_front(44);
170
1
    average.push_front(45);
171
1
    average.print();
172
1
173
1
    EXPECT_FALSE(average.isMoreDiff(6.2));
174
1
175
1
    average.push_back(7.3);
176
1
    average.print();
177
1
178
1
    EXPECT_FALSE(average.isMoreDiff(9.2));
179
1
}
180
181
TEST(StatisticClass, mode)
182
1
{
183
1
    STATISTIC<double> average(22);
184
1
    average.push_back(29.62);
185
1
    average.push_back(29.71);
186
1
    average.push_back(30.19);
187
1
    average.push_back(33.5);
188
1
    average.push_back(30.31);
189
1
    average.push_back(30.81);
190
1
    average.push_back(30.87);
191
1
    average.push_back(31.25);
192
1
    average.push_back(31.31);
193
1
    average.push_back(31.56);
194
1
    average.push_back(31.87);
195
1
    average.push_back(31.94);
196
1
    average.push_back(32.13);
197
1
    average.push_back(32.13);  //to
198
1
    average.push_back(32.63);
199
1
200
1
    average.print();
201
1
    std::cout << "1 MODE: " << average.mode() << std::endl;
202
2
    EXPECT_DOUBLE_EQ(32.13,average.mode()) << "ZLA DOMINANTA 32.13";
203
1
    average.push_back(33.5);
204
1
    average.push_back(33.5);
205
1
    std::cout << "2 MODE: " << average.mode() << std::endl;
206
2
    EXPECT_DOUBLE_EQ(33.5,average.mode()) << "ZLA DOMINANTA 33.5";
207
1
}
208
TEST(StatisticClass, modeOne)
209
1
{
210
1
    STATISTIC<double> average(1);
211
1
    average.push_back(29.62);
212
1
    average.print();
213
1
    std::cout << "1 MODE: " << average.mode() << std::endl;
214
2
    EXPECT_DOUBLE_EQ(29.62,average.mode()) << "ZLA DOMINANTA 32.13";
215
1
}
216
TEST(StatisticClass, modeTwo)
217
1
{
218
1
    STATISTIC<double> average(10);
219
1
    average.push_back(29.62);
220
1
    average.push_back(28.62);
221
1
    average.print();
222
1
    std::cout << "1 MODE: " << average.mode() << std::endl;
223
2
    EXPECT_DOUBLE_EQ(28.62,average.mode()) << "ZLA DOMINANTA 32.13";
224
1
}
225
TEST(StatisticClass, modeThree)
226
1
{
227
1
    STATISTIC<double> average(10);
228
1
    average.push_back(29.62);
229
1
    average.push_back(28.62);
230
1
    average.push_back(29.63);
231
1
    average.print();
232
1
    std::cout << "1 MODE: " << average.mode() << std::endl;
233
2
    EXPECT_DOUBLE_EQ(28.62,average.mode()) << "ZLA DOMINANTA 32.13";
234
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/libs/emoji/emoji.cpp
Line
Count
Source (jump to first uncovered line)
1
#include <sstream>
2
#include "emoji.h"
3
4
EMOJI::EMOJI()
5
0
{
6
0
7
0
}
8
9
std::string EMOJI::emoji(E_emoji e)
10
26
{
11
26
    switch (e) {
12
16
    case E_emoji::NORTH_EAST_ARROW:
13
16
        return HEX_STR::hexToStr("E28697");
14
16
    case E_emoji::SOUTH_EAST_ARROW:
15
3
        return HEX_STR::hexToStr("E28698");
16
16
    case E_emoji::NORTH_WEST_ARROW:
17
0
        return HEX_STR::hexToStr("E28696");
18
16
    case E_emoji::SOUTH_WEST_ARROW:
19
0
        return HEX_STR::hexToStr("E28699");
20
16
    case E_emoji::LEFT_RIGHT_ARROW:
21
0
        return HEX_STR::hexToStr("E28694");
22
16
    case E_emoji::UP_DOWN_ARROW:
23
0
        return HEX_STR::hexToStr("E28695");
24
16
    case E_emoji::ALARM_CLOCK:
25
0
        return HEX_STR::hexToStr("E28FB0");
26
16
    case E_emoji::SUN_WITH_FACE:
27
0
        return HEX_STR::hexToStr("F09F8C9E");
28
16
    case E_emoji::SNOWFLAKE:
29
0
        return HEX_STR::hexToStr("E29D84");
30
16
    case E_emoji::HEAVY_BLACK_HEART:
31
0
        return HEX_STR::hexToStr("E29DA4");
32
16
    case E_emoji::WARNING_SIGN:
33
1
        return HEX_STR::hexToStr("E29AA0");
34
16
    case E_emoji::CHART_WITH_DOWNWARDS_TREND:
35
2
        return HEX_STR::hexToStr("F09F9389");
36
16
    case E_emoji::CHART_WITH_UPWARDS_TREND:
37
2
        return HEX_STR::hexToStr("F09F9388");
38
16
    case E_emoji::THUNDER_CLOUD_AND_RAIN:
39
2
        return HEX_STR::hexToStr("E29B88");
40
0
41
0
    }
42
26
    return"ok";
43
26
}
44
45
std::string HEX_STR::hexToStr(const std::string& hex)
46
26
{
47
26
    std::string res;
48
26
    res.reserve(hex.size() / 2);
49
108
    for (unsigned int i = 0; i < hex.size(); i += 2)
50
82
    {
51
82
        std::istringstream iss(hex.substr(i, 2));
52
82
        int temp;
53
82
        iss >> std::hex >> temp;
54
82
        res += static_cast<char>(temp);
55
82
    }
56
26
    return res;
57
26
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/libs/emoji/emoji.cpp
Line
Count
Source (jump to first uncovered line)
1
#include <sstream>
2
#include "emoji.h"
3
4
EMOJI::EMOJI()
5
0
{
6
0
7
0
}
8
9
std::string EMOJI::emoji(E_emoji e)
10
26
{
11
26
    switch (e) {
12
26
    case E_emoji::NORTH_EAST_ARROW:
13
16
        return HEX_STR::hexToStr("E28697");
14
26
    case E_emoji::SOUTH_EAST_ARROW:
15
3
        return HEX_STR::hexToStr("E28698");
16
26
    case E_emoji::NORTH_WEST_ARROW:
17
0
        return HEX_STR::hexToStr("E28696");
18
26
    case E_emoji::SOUTH_WEST_ARROW:
19
0
        return HEX_STR::hexToStr("E28699");
20
26
    case E_emoji::LEFT_RIGHT_ARROW:
21
0
        return HEX_STR::hexToStr("E28694");
22
26
    case E_emoji::UP_DOWN_ARROW:
23
0
        return HEX_STR::hexToStr("E28695");
24
26
    case E_emoji::ALARM_CLOCK:
25
0
        return HEX_STR::hexToStr("E28FB0");
26
26
    case E_emoji::SUN_WITH_FACE:
27
0
        return HEX_STR::hexToStr("F09F8C9E");
28
26
    case E_emoji::SNOWFLAKE:
29
0
        return HEX_STR::hexToStr("E29D84");
30
26
    case E_emoji::HEAVY_BLACK_HEART:
31
0
        return HEX_STR::hexToStr("E29DA4");
32
26
    case E_emoji::WARNING_SIGN:
33
1
        return HEX_STR::hexToStr("E29AA0");
34
26
    case E_emoji::CHART_WITH_DOWNWARDS_TREND:
35
2
        return HEX_STR::hexToStr("F09F9389");
36
26
    case E_emoji::CHART_WITH_UPWARDS_TREND:
37
2
        return HEX_STR::hexToStr("F09F9388");
38
26
    case E_emoji::THUNDER_CLOUD_AND_RAIN:
39
2
        return HEX_STR::hexToStr("E29B88");
40
0
41
0
    }
42
0
    return"ok";
43
0
}
44
45
std::string HEX_STR::hexToStr(const std::string& hex)
46
26
{
47
26
    std::string res;
48
26
    res.reserve(hex.size() / 2);
49
108
    for (unsigned int i = 0; i < hex.size(); i += 2)
50
82
    {
51
82
        std::istringstream iss(hex.substr(i, 2));
52
82
        int temp;
53
82
        iss >> std::hex >> temp;
54
82
        res += static_cast<char>(temp);
55
82
    }
56
26
    return res;
57
26
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/libs/event_counters/event/event_command.cpp
Line
Count
Source
1
#include "event_command.h"
2
3
event_command::event_command(const std::string& name):  event_counters(name)
4
208
{
5
208
6
208
}
7
8
std::string event_command::help()
9
3
{
10
3
    return "event command";
11
3
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/libs/event_counters/event/event_command.cpp
Line
Count
Source
1
#include "event_command.h"
2
3
event_command::event_command(const std::string& name):  event_counters(name)
4
208
{
5
208
6
208
}
7
8
std::string event_command::help()
9
3
{
10
3
    return "event command";
11
3
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/libs/event_counters/event/event_mpd.cpp
Line
Count
Source
1
#include "event_mpd.h"
2
3
event_mpd::event_mpd(const std::string& name): event_counters(name)
4
208
{
5
208
6
208
}
7
8
std::string event_mpd::help()
9
2
{
10
2
    return "event from MPD";
11
2
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/libs/event_counters/event/event_mpd.cpp
Line
Count
Source
1
#include "event_mpd.h"
2
3
event_mpd::event_mpd(const std::string& name): event_counters(name)
4
208
{
5
208
6
208
}
7
8
std::string event_mpd::help()
9
2
{
10
2
    return "event from MPD";
11
2
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/libs/event_counters/event/event_pilot.cpp
Line
Count
Source
1
#include "event_pilot.h"
2
3
event_pilot::event_pilot(const std::string& name): event_counters(name)
4
208
{
5
208
6
208
}
7
8
std::string event_pilot::help()
9
3
{
10
3
    return "pilot events";
11
3
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/libs/event_counters/event/event_pilot.cpp
Line
Count
Source
1
#include "event_pilot.h"
2
3
event_pilot::event_pilot(const std::string& name): event_counters(name)
4
208
{
5
208
6
208
}
7
8
std::string event_pilot::help()
9
3
{
10
3
    return "pilot events";
11
3
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/libs/event_counters/event/event_unknown.cpp
Line
Count
Source
1
#include "event_unknown.h"
2
3
event_unknown::event_unknown(const std::string& name) : event_counters(name), name(name)
4
260
{
5
260
6
260
}
7
8
std::string event_unknown::help()
9
38
{
10
38
    return  name+" event";
11
38
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/libs/event_counters/event/event_unknown.cpp
Line
Count
Source
1
#include "event_unknown.h"
2
3
event_unknown::event_unknown(const std::string& name) : event_counters(name), name(name)
4
260
{
5
260
6
260
}
7
8
std::string event_unknown::help()
9
38
{
10
38
    return  name+" event";
11
38
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/libs/event_counters/event/new_connect_event.cpp
Line
Count
Source
1
#include "new_connect_event.h"
2
#include <iostream>
3
new_Connect_Event::new_Connect_Event(const std::string& name) : event_counters(name)
4
208
{
5
208
6
208
}
7
8
new_Connect_Event::~new_Connect_Event()
9
208
{
10
208
    std::cout << " kasujemy obiekt" << std::endl;
11
208
}
12
13
std::string new_Connect_Event::help()
14
3
{
15
3
    return "connection start event";
16
3
}
17
18
19
20
21
22
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/libs/event_counters/event/new_connect_event.cpp
Line
Count
Source
1
#include "new_connect_event.h"
2
#include <iostream>
3
new_Connect_Event::new_Connect_Event(const std::string& name) : event_counters(name)
4
208
{
5
208
6
208
}
7
8
new_Connect_Event::~new_Connect_Event()
9
208
{
10
208
    std::cout << " kasujemy obiekt" << std::endl;
11
208
}
12
13
std::string new_Connect_Event::help()
14
3
{
15
3
    return "connection start event";
16
3
}
17
18
19
20
21
22
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/libs/event_counters/event_counters.cpp
Line
Count
Source
1
#include "event_counters.h"
2
#include <iostream>
3
#include <iomanip>
4
#include <ctime>
5
#include <sstream>
6
#include <string>
7
#include <algorithm>
8
9
event_counters::event_counters(std::string name) : eventName(std::move(name))
10
1.09k
{
11
1.09k
12
1.09k
}
13
14
int event_counters::howManyEvent()
15
42
{
16
42
    std::lock_guard < std::mutex > lock ( eventMutex);
17
42
    return static_cast<int>( eventList.size() );
18
42
}
19
20
void event_counters::addEvent(const std::string& note)
21
5.11k
{
22
5.11k
    eventStruct d;
23
5.11k
    std::ostringstream oss;
24
5.11k
25
5.11k
    auto t = std::time(nullptr);
26
5.11k
    auto tm = *std::localtime(&t);
27
5.11k
    oss << std::put_time(&tm, "%d-%m-%Y %H:%M:%S");
28
5.11k
29
5.11k
    d.date = oss.str();
30
5.11k
    d.note = note;
31
5.11k
    d.posixTime = static_cast<unsigned int> (std::time(nullptr));
32
5.11k
    std::lock_guard < std::mutex > lock ( eventMutex);
33
5.11k
    eventList.push_back(d);
34
5.11k
}
35
36
std::string event_counters::getEvent()
37
37
{
38
37
    std::stringstream ret;
39
37
    ret << "Event: " << help() << "\n";
40
37
    std::lock_guard <std::mutex> lock(eventMutex);
41
37
    int k =0;
42
8.27k
    for (auto i : eventList){
43
8.27k
        ret << ++k << "\t" << i.date << "     " <<  i.note << "\n";
44
8.27k
    }
45
37
    ret << "\n event per last minute: " << getLast1minNumberEvent_NO_Mutex() << "\n------------------------------";
46
37
    return ret.str();
47
37
}
48
49
void event_counters::clearEvent()
50
3
{
51
3
    std::lock_guard <std::mutex> lock(eventMutex);
52
3
    eventList.clear();
53
3
}
54
55
void event_counters::clearEvent(unsigned int from, unsigned int to)
56
5
{
57
5
    if (to < from){
58
1
        return;
59
1
    }
60
5
    auto max = static_cast<unsigned int>( eventList.size() );
61
4
62
4
    if (max < to){
63
2
        to = max;
64
2
    }
65
4
    if(max<from){
66
1
        from = max;
67
1
        to = max;
68
1
    }
69
4
    std::lock_guard <std::mutex> lock(eventMutex);
70
4
    eventList.erase(eventList.begin()+from, eventList.begin()+to);
71
4
}
72
73
unsigned int event_counters::getLast1minNumberEvent()
74
13
{
75
13
    std::lock_guard <std::mutex> lock(eventMutex);
76
13
    return getLast1minNumberEvent_NO_Mutex();
77
13
}
78
79
std::string event_counters::getEventName()
80
1.09k
{
81
1.09k
    return eventName;
82
1.09k
}
83
84
unsigned int event_counters::getLast1minNumberEvent_NO_Mutex()
85
50
{
86
50
    unsigned int k = 0;
87
50
    if (eventList.empty())
88
50
        return k;
89
50
    unsigned int lastPosix = static_cast<unsigned int> (std::time(nullptr));// eventList.at(eventList.size()-1).posixTime;
90
47
91
8.87k
    for (auto i = eventList.size()-1; i != -1; i--)
92
8.82k
    {
93
8.82k
        if(eventList.at(i).posixTime+60 > lastPosix)
94
8.82k
            k++;
95
8.82k
        else
96
8.82k
            break;
97
8.82k
    }
98
47
    return k;
99
50
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/libs/event_counters/event_counters.cpp
Line
Count
Source
1
#include "event_counters.h"
2
#include <iostream>
3
#include <iomanip>
4
#include <ctime>
5
#include <sstream>
6
#include <string>
7
#include <algorithm>
8
9
event_counters::event_counters(std::string name) : eventName(std::move(name))
10
1.09k
{
11
1.09k
12
1.09k
}
13
14
int event_counters::howManyEvent()
15
42
{
16
42
    std::lock_guard < std::mutex > lock ( eventMutex);
17
42
    return static_cast<int>( eventList.size() );
18
42
}
19
20
void event_counters::addEvent(const std::string& note)
21
5.11k
{
22
5.11k
    eventStruct d;
23
5.11k
    std::ostringstream oss;
24
5.11k
25
5.11k
    auto t = std::time(nullptr);
26
5.11k
    auto tm = *std::localtime(&t);
27
5.11k
    oss << std::put_time(&tm, "%d-%m-%Y %H:%M:%S");
28
5.11k
29
5.11k
    d.date = oss.str();
30
5.11k
    d.note = note;
31
5.11k
    d.posixTime = static_cast<unsigned int> (std::time(nullptr));
32
5.11k
    std::lock_guard < std::mutex > lock ( eventMutex);
33
5.11k
    eventList.push_back(d);
34
5.11k
}
35
36
std::string event_counters::getEvent()
37
37
{
38
37
    std::stringstream ret;
39
37
    ret << "Event: " << help() << "\n";
40
37
    std::lock_guard <std::mutex> lock(eventMutex);
41
37
    int k =0;
42
8.27k
    for (auto i : eventList){
43
8.27k
        ret << ++k << "\t" << i.date << "     " <<  i.note << "\n";
44
8.27k
    }
45
37
    ret << "\n event per last minute: " << getLast1minNumberEvent_NO_Mutex() << "\n------------------------------";
46
37
    return ret.str();
47
37
}
48
49
void event_counters::clearEvent()
50
3
{
51
3
    std::lock_guard <std::mutex> lock(eventMutex);
52
3
    eventList.clear();
53
3
}
54
55
void event_counters::clearEvent(unsigned int from, unsigned int to)
56
5
{
57
5
    if (to < from){
58
1
        return;
59
1
    }
60
4
    auto max = static_cast<unsigned int>( eventList.size() );
61
4
62
4
    if (max < to){
63
2
        to = max;
64
2
    }
65
4
    if(max<from){
66
1
        from = max;
67
1
        to = max;
68
1
    }
69
4
    std::lock_guard <std::mutex> lock(eventMutex);
70
4
    eventList.erase(eventList.begin()+from, eventList.begin()+to);
71
4
}
72
73
unsigned int event_counters::getLast1minNumberEvent()
74
13
{
75
13
    std::lock_guard <std::mutex> lock(eventMutex);
76
13
    return getLast1minNumberEvent_NO_Mutex();
77
13
}
78
79
std::string event_counters::getEventName()
80
1.09k
{
81
1.09k
    return eventName;
82
1.09k
}
83
84
unsigned int event_counters::getLast1minNumberEvent_NO_Mutex()
85
50
{
86
50
    unsigned int k = 0;
87
50
    if (eventList.empty())
88
3
        return k;
89
47
    unsigned int lastPosix = static_cast<unsigned int> (std::time(nullptr));// eventList.at(eventList.size()-1).posixTime;
90
47
91
8.87k
    for (auto i = eventList.size()-1; i != -1; i--)
92
8.82k
    {
93
8.82k
        if(eventList.at(i).posixTime+60 > lastPosix)
94
8.82k
            k++;
95
1
        else
96
1
            break;
97
8.82k
    }
98
47
    return k;
99
47
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/libs/event_counters/event_counters_handler.cpp
Line
Count
Source
1
#include "event_counters_handler.h"
2
#include "event/new_connect_event.h"
3
#include "event/event_unknown.h"
4
#include "event/event_mpd.h"
5
#include "event/event_pilot.h"
6
#include "event/event_command.h"
7
8
9
event_counters_handler::event_counters_handler()
10
208
{
11
208
    std::shared_ptr <event_counters> newConnectEvent (new new_Connect_Event("connections") );
12
208
    eventCountersMap.insert( std::make_pair( newConnectEvent->getEventName(), newConnectEvent ) );
13
208
14
208
    std::shared_ptr <event_counters> newUnknownEvent (new event_unknown("unknown") );
15
208
    eventCountersMap.insert( std::make_pair( newUnknownEvent->getEventName(), newUnknownEvent ) );
16
208
17
208
    std::shared_ptr <event_counters> eventMPD (new event_mpd("mpd") );
18
208
    eventCountersMap.insert( std::make_pair( eventMPD->getEventName(), eventMPD ) );
19
208
20
208
    std::shared_ptr <event_counters> eventPilot (new event_pilot("pilot") );
21
208
    eventCountersMap.insert( std::make_pair( eventPilot->getEventName(), eventPilot ) );
22
208
23
208
    std::shared_ptr <event_counters> eventCommand (new event_command("command") );
24
208
    eventCountersMap.insert( std::make_pair( eventCommand->getEventName(), eventCommand ) );
25
208
}
26
27
std::shared_ptr<event_counters> event_counters_handler::run(const std::string& name)
28
5.21k
{
29
5.21k
30
5.21k
    if (eventCountersMap.find(name) == eventCountersMap.end()){
31
52
        addEvent(name);
32
52
    }
33
5.21k
    return eventCountersMap[name];
34
5.21k
}
35
36
std::string event_counters_handler::getListPossibleEvents()
37
2
{
38
2
    std::string result;
39
2
40
13
    for( auto iter= eventCountersMap.begin();iter != eventCountersMap.end(); ++iter ) {
41
11
        result+= iter->first;
42
11
        result+= "\n";
43
11
    }
44
2
    return result;
45
2
}
46
47
std::string event_counters_handler::help(const std::string& name)
48
3
{
49
3
    std::string result;
50
3
51
3
    if (name.empty()){
52
13
        for( auto iter= eventCountersMap.begin();iter != eventCountersMap.end(); ++iter ) {
53
11
            result+= iter->second->help();
54
11
            result+= "\n------------------------------\n";
55
11
        }
56
2
    }
57
3
    else{
58
1
        result = eventCountersMap[name]->help();
59
1
    }
60
3
61
3
    return result;
62
3
}
63
std::mutex event_counters_handler::echMutex;
64
65
void event_counters_handler::addEvent(const std::string& name)
66
52
{
67
52
    std::lock_guard <std::mutex> lock(event_counters_handler::echMutex);
68
52
    std::shared_ptr <event_counters> newUnknownEvent (new event_unknown(name) );
69
52
    eventCountersMap.insert( std::make_pair( newUnknownEvent->getEventName(), newUnknownEvent ) );
70
52
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/libs/event_counters/event_counters_handler.cpp
Line
Count
Source
1
#include "event_counters_handler.h"
2
#include "event/new_connect_event.h"
3
#include "event/event_unknown.h"
4
#include "event/event_mpd.h"
5
#include "event/event_pilot.h"
6
#include "event/event_command.h"
7
8
9
event_counters_handler::event_counters_handler()
10
208
{
11
208
    std::shared_ptr <event_counters> newConnectEvent (new new_Connect_Event("connections") );
12
208
    eventCountersMap.insert( std::make_pair( newConnectEvent->getEventName(), newConnectEvent ) );
13
208
14
208
    std::shared_ptr <event_counters> newUnknownEvent (new event_unknown("unknown") );
15
208
    eventCountersMap.insert( std::make_pair( newUnknownEvent->getEventName(), newUnknownEvent ) );
16
208
17
208
    std::shared_ptr <event_counters> eventMPD (new event_mpd("mpd") );
18
208
    eventCountersMap.insert( std::make_pair( eventMPD->getEventName(), eventMPD ) );
19
208
20
208
    std::shared_ptr <event_counters> eventPilot (new event_pilot("pilot") );
21
208
    eventCountersMap.insert( std::make_pair( eventPilot->getEventName(), eventPilot ) );
22
208
23
208
    std::shared_ptr <event_counters> eventCommand (new event_command("command") );
24
208
    eventCountersMap.insert( std::make_pair( eventCommand->getEventName(), eventCommand ) );
25
208
}
26
27
std::shared_ptr<event_counters> event_counters_handler::run(const std::string& name)
28
5.21k
{
29
5.21k
30
5.21k
    if (eventCountersMap.find(name) == eventCountersMap.end()){
31
52
        addEvent(name);
32
52
    }
33
5.21k
    return eventCountersMap[name];
34
5.21k
}
35
36
std::string event_counters_handler::getListPossibleEvents()
37
2
{
38
2
    std::string result;
39
2
40
13
    for( auto iter= eventCountersMap.begin();iter != eventCountersMap.end(); ++iter ) {
41
11
        result+= iter->first;
42
11
        result+= "\n";
43
11
    }
44
2
    return result;
45
2
}
46
47
std::string event_counters_handler::help(const std::string& name)
48
3
{
49
3
    std::string result;
50
3
51
3
    if (name.empty()){
52
13
        for( auto iter= eventCountersMap.begin();iter != eventCountersMap.end(); ++iter ) {
53
11
            result+= iter->second->help();
54
11
            result+= "\n------------------------------\n";
55
11
        }
56
2
    }
57
1
    else{
58
1
        result = eventCountersMap[name]->help();
59
1
    }
60
3
61
3
    return result;
62
3
}
63
std::mutex event_counters_handler::echMutex;
64
65
void event_counters_handler::addEvent(const std::string& name)
66
52
{
67
52
    std::lock_guard <std::mutex> lock(event_counters_handler::echMutex);
68
52
    std::shared_ptr <event_counters> newUnknownEvent (new event_unknown(name) );
69
52
    eventCountersMap.insert( std::make_pair( newUnknownEvent->getEventName(), newUnknownEvent ) );
70
52
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/libs/event_counters/test/event_BT.cpp
Line
Count
Source
1
#include <gtest/gtest.h>
2
#include "test_data.h"
3
#include "../../../iDom_server_OOP/src/iDomTools/test/iDomTools_fixture.h"
4
#include "../event_counters_handler.h"
5
6
class event_counter_fixture : public iDomTOOLS_ClassTest
7
{
8
public:
9
     event_counters_handler mainEvent;
10
     std::string msg = "info";
11
     std::string testEvent = "testEvent";
12
5
     void preper1001Event(){
13
5
         int counter = 1000;
14
5
         EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),0);
15
5
         mainEvent.run(testEvent)->addEvent(msg);
16
5
         EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),1);
17
5
         std::string returnedString = mainEvent.run(testEvent)->getEvent();
18
5
         EXPECT_THAT(returnedString, testing::HasSubstr(msg));
19
5
         EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),1);
20
5
21
5.00k
         for (int i = 1; i!= counter; counter--)
22
4.99k
         {
23
4.99k
             mainEvent.run(testEvent)->addEvent(msg);
24
4.99k
             if(counter == 500)
25
4.99k
                 mainEvent.run(testEvent)->addEvent("cyniu");
26
4.99k
         }
27
5
         EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),1001);
28
5
         returnedString = mainEvent.run(testEvent)->getEvent();
29
5
         EXPECT_THAT(returnedString, testing::HasSubstr("cyniu"));
30
5
     }
31
};
32
33
TEST_F(event_counter_fixture, add_get_clear_event)
34
1
{
35
1
    EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),0);
36
1
    mainEvent.run(testEvent)->addEvent(msg);
37
1
    EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),1);
38
1
    std::string returnedString = mainEvent.run(testEvent)->getEvent();
39
1
    EXPECT_THAT(returnedString, testing::HasSubstr(msg));
40
1
    EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),1);
41
1
    mainEvent.run(testEvent)->clearEvent();
42
1
    EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),0);
43
1
}
44
45
TEST_F(event_counter_fixture, clear_middle_part_of_event_small_big)
46
1
{
47
1
    preper1001Event();
48
1
    mainEvent.run(testEvent)->clearEvent(400,600);
49
1
    EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),801);
50
1
    std::string returnedString = mainEvent.run(testEvent)->getEvent();
51
1
    EXPECT_THAT(returnedString, testing::Not(testing::HasSubstr("cyniu")));
52
1
}
53
54
TEST_F(event_counter_fixture, clear_middle_part_of_event_big_small)
55
1
{
56
1
    preper1001Event();
57
1
    mainEvent.run(testEvent)->clearEvent(600,400);
58
1
    EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),1001);
59
1
    std::string returnedString = mainEvent.run(testEvent)->getEvent();
60
1
    EXPECT_THAT(returnedString,testing::HasSubstr("cyniu"));
61
1
}
62
63
TEST_F(event_counter_fixture, clear_middle_part_of_event_to_max)
64
1
{
65
1
    preper1001Event();
66
1
    mainEvent.run(testEvent)->clearEvent(400,1600);
67
1
    EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),400);
68
1
    std::string returnedString = mainEvent.run(testEvent)->getEvent();
69
1
    EXPECT_THAT(returnedString, testing::Not(testing::HasSubstr("cyniu")));
70
1
}
71
72
TEST_F(event_counter_fixture, clear_middle_part_of_event_from_max)
73
1
{
74
1
    preper1001Event();
75
1
    mainEvent.run(testEvent)->clearEvent(1400,1600);
76
1
    EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),1001);
77
1
    std::string returnedString = mainEvent.run(testEvent)->getEvent();
78
1
    EXPECT_THAT(returnedString, testing::HasSubstr("cyniu") );
79
1
}
80
81
TEST_F(event_counter_fixture, getListPossibleEvents)
82
1
{
83
1
    mainEvent.run("INFO")->addEvent("kokolino");
84
1
   std::string returnedString = mainEvent.getListPossibleEvents();
85
1
   std::cout << "wynik: " << returnedString << std::endl;
86
1
   EXPECT_THAT(returnedString, testing::HasSubstr("INFO") );
87
1
}
88
89
TEST_F(event_counter_fixture, getHelp)
90
1
{
91
1
   mainEvent.run("INFO")->addEvent("kokolino");
92
1
   std::string returnedString = mainEvent.help("connections");
93
1
   std::cout << "wynik: " << returnedString << std::endl;
94
1
   EXPECT_THAT(returnedString, testing::HasSubstr("start") );
95
1
   returnedString = mainEvent.help("");
96
1
   std::cout << "wynik: " << returnedString << std::endl;
97
1
   EXPECT_THAT(returnedString, testing::HasSubstr("pilot") );
98
1
}
99
100
TEST_F(event_counter_fixture, getLast1minNumberEvent)
101
1
{
102
1
    preper1001Event();
103
1
    mainEvent.run(testEvent)->eventList.at(500).posixTime -= 65;
104
1
    EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),1001);
105
1
    EXPECT_EQ(mainEvent.run(testEvent)->getLast1minNumberEvent(),500);
106
1
}
107
TEST_F(event_counter_fixture, getLast1minNumberEventWhenEmpty)
108
1
{
109
1
    EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),0);
110
    EXPECT_EQ(mainEvent.run(testEvent)->getLast1minNumberEvent(),0);
111
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/libs/event_counters/test/event_BT.cpp
Line
Count
Source
1
#include <gtest/gtest.h>
2
#include "test_data.h"
3
#include "../../../iDom_server_OOP/src/iDomTools/test/iDomTools_fixture.h"
4
#include "../event_counters_handler.h"
5
6
class event_counter_fixture : public iDomTOOLS_ClassTest
7
{
8
public:
9
     event_counters_handler mainEvent;
10
     std::string msg = "info";
11
     std::string testEvent = "testEvent";
12
5
     void preper1001Event(){
13
5
         int counter = 1000;
14
5
         EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),0);
15
5
         mainEvent.run(testEvent)->addEvent(msg);
16
5
         EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),1);
17
5
         std::string returnedString = mainEvent.run(testEvent)->getEvent();
18
5
         EXPECT_THAT(returnedString, testing::HasSubstr(msg));
19
5
         EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),1);
20
5
21
5.00k
         for (int i = 1; i!= counter; counter--)
22
4.99k
         {
23
4.99k
             mainEvent.run(testEvent)->addEvent(msg);
24
4.99k
             if(counter == 500)
25
5
                 mainEvent.run(testEvent)->addEvent("cyniu");
26
4.99k
         }
27
5
         EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),1001);
28
5
         returnedString = mainEvent.run(testEvent)->getEvent();
29
5
         EXPECT_THAT(returnedString, testing::HasSubstr("cyniu"));
30
5
     }
31
};
32
33
TEST_F(event_counter_fixture, add_get_clear_event)
34
1
{
35
1
    EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),0);
36
1
    mainEvent.run(testEvent)->addEvent(msg);
37
1
    EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),1);
38
1
    std::string returnedString = mainEvent.run(testEvent)->getEvent();
39
1
    EXPECT_THAT(returnedString, testing::HasSubstr(msg));
40
1
    EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),1);
41
1
    mainEvent.run(testEvent)->clearEvent();
42
1
    EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),0);
43
1
}
44
45
TEST_F(event_counter_fixture, clear_middle_part_of_event_small_big)
46
1
{
47
1
    preper1001Event();
48
1
    mainEvent.run(testEvent)->clearEvent(400,600);
49
1
    EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),801);
50
1
    std::string returnedString = mainEvent.run(testEvent)->getEvent();
51
1
    EXPECT_THAT(returnedString, testing::Not(testing::HasSubstr("cyniu")));
52
1
}
53
54
TEST_F(event_counter_fixture, clear_middle_part_of_event_big_small)
55
1
{
56
1
    preper1001Event();
57
1
    mainEvent.run(testEvent)->clearEvent(600,400);
58
1
    EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),1001);
59
1
    std::string returnedString = mainEvent.run(testEvent)->getEvent();
60
1
    EXPECT_THAT(returnedString,testing::HasSubstr("cyniu"));
61
1
}
62
63
TEST_F(event_counter_fixture, clear_middle_part_of_event_to_max)
64
1
{
65
1
    preper1001Event();
66
1
    mainEvent.run(testEvent)->clearEvent(400,1600);
67
1
    EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),400);
68
1
    std::string returnedString = mainEvent.run(testEvent)->getEvent();
69
1
    EXPECT_THAT(returnedString, testing::Not(testing::HasSubstr("cyniu")));
70
1
}
71
72
TEST_F(event_counter_fixture, clear_middle_part_of_event_from_max)
73
1
{
74
1
    preper1001Event();
75
1
    mainEvent.run(testEvent)->clearEvent(1400,1600);
76
1
    EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),1001);
77
1
    std::string returnedString = mainEvent.run(testEvent)->getEvent();
78
1
    EXPECT_THAT(returnedString, testing::HasSubstr("cyniu") );
79
1
}
80
81
TEST_F(event_counter_fixture, getListPossibleEvents)
82
1
{
83
1
    mainEvent.run("INFO")->addEvent("kokolino");
84
1
   std::string returnedString = mainEvent.getListPossibleEvents();
85
1
   std::cout << "wynik: " << returnedString << std::endl;
86
1
   EXPECT_THAT(returnedString, testing::HasSubstr("INFO") );
87
1
}
88
89
TEST_F(event_counter_fixture, getHelp)
90
1
{
91
1
   mainEvent.run("INFO")->addEvent("kokolino");
92
1
   std::string returnedString = mainEvent.help("connections");
93
1
   std::cout << "wynik: " << returnedString << std::endl;
94
1
   EXPECT_THAT(returnedString, testing::HasSubstr("start") );
95
1
   returnedString = mainEvent.help("");
96
1
   std::cout << "wynik: " << returnedString << std::endl;
97
1
   EXPECT_THAT(returnedString, testing::HasSubstr("pilot") );
98
1
}
99
100
TEST_F(event_counter_fixture, getLast1minNumberEvent)
101
1
{
102
1
    preper1001Event();
103
1
    mainEvent.run(testEvent)->eventList.at(500).posixTime -= 65;
104
1
    EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),1001);
105
1
    EXPECT_EQ(mainEvent.run(testEvent)->getLast1minNumberEvent(),500);
106
1
}
107
TEST_F(event_counter_fixture, getLast1minNumberEventWhenEmpty)
108
1
{
109
1
    EXPECT_EQ(mainEvent.run(testEvent)->howManyEvent(),0);
110
1
    EXPECT_EQ(mainEvent.run(testEvent)->getLast1minNumberEvent(),0);
111
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/libs/sunrise-sunset/sunriseset.cpp
Line
Count
Source (jump to first uncovered line)
1
#include "sunriseset.h"
2
3
double SunRiseSet::FNday(int y, int m, int d, float h)
4
44
{
5
44
    long int luku = - 7 * (y + (m + 9)/12)/4 + 275*m/9 + d;
6
44
7
44
    // Typecasting needed for TClite on PC DOS at least, to avoid product overflow
8
44
    luku+= (long int)y*367;
9
44
10
44
    return (double)luku - 730531.5 + h/24.0;
11
44
}
12
double SunRiseSet::FNrange(double x)
13
132
{
14
132
    double b = x / tpi;
15
132
    double a = tpi * (b - (long)(b));
16
132
    if (a < 0) a = tpi + a;
17
132
    return a;
18
132
}
19
20
double SunRiseSet::f0(double lat, double declin)
21
44
{
22
44
    double fo,dfo;
23
44
    // Correction: different sign at S HS
24
44
    dfo = rads*(0.5*SunDia + AirRefr); if (lat < 0.0) dfo = -dfo;
25
44
    fo = tan(declin + dfo) * tan(lat*rads);
26
44
27
44
    if (fo > 0.99999) fo=1.0; // to avoid overflow //
28
44
    fo = asin(fo) + pi/2.0;
29
44
    return fo;
30
44
}
31
32
double SunRiseSet::f1(double lat, double declin)
33
1
{
34
1
    double fi,df1;
35
1
    // Correction: different sign at S HS
36
1
    df1 = rads * 6.0; if (lat < 0.0) df1 = -df1;
37
1
    fi = tan(declin + df1) * tan(lat*rads);
38
1
39
1
    if (fi > 0.99999) fi=1.0; // to avoid overflow //
40
1
    fi = asin(fi) + pi/2.0;
41
1
    return fi;
42
1
}
43
44
double SunRiseSet::FNsun(double d)
45
44
{
46
44
    // mean longitude of the Sun
47
44
    L = FNrange(280.461 * rads + .9856474 * rads * d);
48
44
49
44
    // mean anomaly of the Sun
50
44
    g = FNrange(357.528 * rads + .9856003 * rads * d);
51
44
52
44
    // Ecliptic longitude of the Sun
53
44
    return FNrange(L + 1.915 * rads * sin(g) + .02 * rads * sin(2 * g));
54
44
}
55
56
Clock SunRiseSet::gethrmn(double dhr)
57
53
{
58
53
59
53
    int hr,mn;
60
53
61
53
    hr=(int) dhr;
62
53
    mn = (dhr - (double) hr)*60;
63
53
64
53
    Clock ret(hr,mn);
65
53
66
53
    return ret;
67
53
}
68
69
SunRiseSet::SunRiseSet()
70
195
{
71
195
72
195
}
73
74
std::string SunRiseSet::getAllData()
75
1
{
76
1
    double y,m,day,h,latit,longit;
77
1
78
1
    time_t sekunnit;
79
1
    struct tm *p;
80
1
81
1
    // get the date and time from the user
82
1
    // read system date and extract the year
83
1
84
1
    /** First get current time **/
85
1
    time(&sekunnit);
86
1
87
1
    /** Next get localtime **/
88
1
89
1
    p=localtime(&sekunnit);
90
1
    // this is Y2K compliant algorithm
91
1
    y = 1900 + p->tm_year;
92
1
93
1
    m = p->tm_mon + 1;
94
1
    day = p->tm_mday;
95
1
    h = 12;
96
1
97
1
    std::cout << "Input latitude, longitude and timezone\n";
98
1
    latit = LATITUDE;
99
1
    longit = LONGITUDE;
100
1
    // Timezone hours
101
1
    double tzone= TIMEZONE;
102
1
    double d = FNday(y, m, day, h);
103
1
104
1
    // Use FNsun to find the ecliptic longitude of the
105
1
    // Sun
106
1
    double lambda = FNsun(d);
107
1
108
1
    // Obliquity of the ecliptic
109
1
    double obliq = 23.439 * rads - .0000004 * rads * d;
110
1
111
1
    // Find the RA and DEC of the Sun
112
1
    double alpha = atan2(cos(obliq) * sin(lambda), cos(lambda));
113
1
    double delta = asin(sin(obliq) * sin(lambda));
114
1
115
1
    // Find the Equation of Time in minutes
116
1
    // Correction suggested by David Smith
117
1
    double LL = L - alpha;
118
1
    if (L < pi) LL += tpi;
119
1
    double equation = 1440.0 * (1.0 - LL / tpi);
120
1
    double ha = f0(latit,delta);
121
1
    double hb = f1(latit,delta);
122
1
    double twx = hb - ha;   // length of twilight in radians
123
1
    twx = 12.0*twx/pi;      // length of twilight in degrees
124
1
125
1
    // Conversion of angle to hours and minutes //
126
1
    daylen = degs * ha / 7.5;
127
1
    if (daylen<0.0001) {daylen = 0.0;}
128
1
    // arctic winter   //
129
1
130
1
    double riset = 12.0 - 12.0 * ha/pi + tzone - longit/15.0 + equation/60.0;
131
1
    double settm = 12.0 + 12.0 * ha/pi + tzone - longit/15.0 + equation/60.0;
132
1
    //double noont = riset + 12.0 * ha/pi;
133
1
    //double altmax = 90.0 + delta * degs - latit;
134
1
    // Correction suggested by David Smith
135
1
    // to express as degrees from the N horizon
136
1
137
1
    //if (delta * degs > latit ) altmax = 90.0 + latit - delta * degs;
138
1
139
1
    double twam = riset - twx;    // morning twilight begin
140
1
    double twpm = settm + twx;      // evening twilight end
141
1
142
1
    if (riset > 24.0) riset-= 24.0;
143
1
    if (settm > 24.0) settm-= 24.0;
144
1
145
1
    std::stringstream ss;
146
1
    ss << "\n Sunrise and set\n";
147
1
    ss << "===============\n";
148
1
    ss << "  year  : " << y << '\n';
149
1
    ss << "  month : " << m << '\n';
150
1
    ss << "  day   : " << day << "\n\n";
151
1
    ss << "Days until Y2K :  " << d << '\n';
152
1
    ss << "Latitude :  " << latit << ", longitude:  " << longit << '\n';
153
1
    ss << "Timezone :  " << tzone << "\n\n";
154
1
    ss << "Declination : " << delta * degs << '\n';
155
1
    ss << "Daylength   : "<< gethrmn(daylen).m_h<<":"<<gethrmn(daylen).m_min<< " hours \n";
156
1
    ss << "Begin civil twilight: "<<
157
1
                 gethrmn(twam).m_h<<":"<<gethrmn(twam).m_min; std::cout << '\n';
158
1
159
1
    ss << "Sunrise     : "<< gethrmn(riset).m_h<<":"<<gethrmn(riset).m_min; std::cout << '\n';
160
1
    ss << "Sun altitude at noontime ";
161
1
162
1
163
1
    ss << "Sunset      : "<<
164
1
                 gethrmn(settm).m_h<<":"<<gethrmn(settm).m_min; std::cout << '\n';
165
1
    ss << "Civil twilight: "<<
166
1
                 gethrmn(twpm).m_h<<":"<<gethrmn(twpm).m_min; std::cout << '\n';
167
1
    return ss.str();
168
1
}
169
170
void SunRiseSet::setPosition(double LATITUDE, double LONGITUDE, int TIMEZONE)
171
0
{
172
0
    this->LATITUDE = LATITUDE;
173
0
    this->LONGITUDE = LONGITUDE;
174
0
    this->TIMEZONE = TIMEZONE;
175
0
}
176
177
Clock SunRiseSet::getSunRise()
178
25
{
179
25
    double y,m,day,h,latit,longit;
180
25
    time_t sekunnit;
181
25
    struct tm *p;
182
25
    // get the date and time from the user
183
25
    // read system date and extract the year
184
25
185
25
    /** First get current time **/
186
25
    time(&sekunnit);
187
25
188
25
    /** Next get localtime **/
189
25
    p=localtime(&sekunnit);
190
25
    // this is Y2K compliant algorithm
191
25
    y = 1900 + p->tm_year;
192
25
    m = p->tm_mon + 1;
193
25
    day = p->tm_mday;
194
25
    h = 12;
195
25
    latit = LATITUDE;
196
25
    longit = LONGITUDE;
197
25
    // Timezone hours
198
25
    double tzone = TIMEZONE;
199
25
    double d = FNday(y, m, day, h);
200
25
    // Use FNsun to find the ecliptic longitude of the
201
25
    // Sun
202
25
    double lambda = FNsun(d);
203
25
    // Obliquity of the ecliptic
204
25
    double obliq = 23.439 * rads - .0000004 * rads * d;
205
25
    // Find the RA and DEC of the Sun
206
25
    double alpha = atan2(cos(obliq) * sin(lambda), cos(lambda));
207
25
    double delta = asin(sin(obliq) * sin(lambda));
208
25
    double LL = L - alpha;
209
25
    if (L < pi) LL += tpi;
210
25
    double equation = 1440.0 * (1.0 - LL / tpi);
211
25
    double ha = f0(latit,delta);
212
25
    // Conversion of angle to hours and minutes //
213
25
    daylen = degs * ha / 7.5;
214
25
    if (daylen<0.0001) {daylen = 0.0;}
215
25
    // arctic winter   //
216
25
    double riset = 12.0 - 12.0 * ha/pi + tzone - longit/15.0 + equation/60.0;
217
25
218
25
    if (riset > 24.0) riset-= 24.0;
219
25
    return  gethrmn(riset);
220
25
}
221
222
Clock SunRiseSet::getDayLength()
223
7
{
224
7
    double y,m,day,h,latit;
225
7
    time_t sekunnit;
226
7
    struct tm *p;
227
7
228
7
    // get the date and time from the user
229
7
    // read system date and extract the year
230
7
231
7
    /** First get current time **/
232
7
    time(&sekunnit);
233
7
234
7
    /** Next get localtime **/
235
7
    p=localtime(&sekunnit);
236
7
    // this is Y2K compliant algorithm
237
7
    y = 1900 + p->tm_year;
238
7
    m = p->tm_mon + 1;
239
7
    day = p->tm_mday;
240
7
    h = 12;
241
7
    latit = LATITUDE;
242
7
    double d = FNday(y, m, day, h);
243
7
244
7
    // Use FNsun to find the ecliptic longitude of the
245
7
    // Sun
246
7
    double lambda = FNsun(d);
247
7
    // Obliquity of the ecliptic
248
7
    double obliq = 23.439 * rads - .0000004 * rads * d;
249
7
    double delta = asin(sin(obliq) * sin(lambda));
250
7
    // Find the Equation of Time in minutes
251
7
    // Correction suggested by David Smith
252
7
    double ha = f0(latit,delta);
253
7
    // Conversion of angle to hours and minutes //
254
7
    daylen = degs * ha / 7.5;
255
7
    if (daylen<0.0001) {daylen = 0.0;}
256
7
    // arctic winter   //
257
7
258
7
    return  gethrmn(daylen);
259
7
}
260
261
Clock SunRiseSet::getSunSet()
262
11
{
263
11
    double y,m,day,h,latit,longit;
264
11
265
11
    time_t sekunnit;
266
11
    struct tm *p;
267
11
268
11
    // get the date and time from the user
269
11
    // read system date and extract the year
270
11
271
11
    /** First get current time **/
272
11
    time(&sekunnit);
273
11
274
11
    /** Next get localtime **/
275
11
276
11
    p=localtime(&sekunnit);
277
11
    // this is Y2K compliant algorithm
278
11
    y = 1900 + p->tm_year;
279
11
280
11
    m = p->tm_mon + 1;
281
11
    day = p->tm_mday;
282
11
    h = 12;
283
11
284
11
    latit = LATITUDE;
285
11
    longit = LONGITUDE;
286
11
    // Timezone hours
287
11
    double tzone = TIMEZONE;
288
11
289
11
    double d = FNday(y, m, day, h);
290
11
291
11
    // Use FNsun to find the ecliptic longitude of the
292
11
    // Sun
293
11
294
11
    double lambda = FNsun(d);
295
11
296
11
    // Obliquity of the ecliptic
297
11
298
11
    double obliq = 23.439 * rads - .0000004 * rads * d;
299
11
300
11
    // Find the RA and DEC of the Sun
301
11
302
11
    double alpha = atan2(cos(obliq) * sin(lambda), cos(lambda));
303
11
    double delta = asin(sin(obliq) * sin(lambda));
304
11
305
11
306
11
    // Find the Equation of Time in minutes
307
11
    // Correction suggested by David Smith
308
11
309
11
    double LL = L - alpha;
310
11
    if (L < pi) LL += tpi;
311
11
    double equation = 1440.0 * (1.0 - LL / tpi);
312
11
313
11
314
11
    double ha = f0(latit,delta);
315
11
316
11
    // Conversion of angle to hours and minutes //
317
11
    daylen = degs * ha / 7.5;
318
11
    if (daylen<0.0001) {daylen = 0.0;}
319
11
    // arctic winter   //
320
11
321
11
    //double riset = 12.0 - 12.0 * ha/pi + tzone - longit/15.0 + equation/60.0;
322
11
    double settm = 12.0 + 12.0 * ha/pi + tzone - longit/15.0 + equation/60.0;
323
11
324
11
    //if (riset > 24.0) riset-= 24.0;
325
11
    if (settm > 24.0) settm-= 24.0;
326
11
    return  gethrmn(settm);
327
11
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/libs/json/single_include/nlohmann/json.hpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
    __ _____ _____ _____
3
 __|  |   __|     |   | |  JSON for Modern C++
4
|  |  |__   |  |  | | | |  version 3.2.0
5
|_____|_____|_____|_|___|  https://github.com/nlohmann/json
6
7
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
8
SPDX-License-Identifier: MIT
9
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
10
11
Permission is hereby  granted, free of charge, to any  person obtaining a copy
12
of this software and associated  documentation files (the "Software"), to deal
13
in the Software  without restriction, including without  limitation the rights
14
to  use, copy,  modify, merge,  publish, distribute,  sublicense, and/or  sell
15
copies  of  the Software,  and  to  permit persons  to  whom  the Software  is
16
furnished to do so, subject to the following conditions:
17
18
The above copyright notice and this permission notice shall be included in all
19
copies or substantial portions of the Software.
20
21
THE SOFTWARE  IS PROVIDED "AS  IS", WITHOUT WARRANTY  OF ANY KIND,  EXPRESS OR
22
IMPLIED,  INCLUDING BUT  NOT  LIMITED TO  THE  WARRANTIES OF  MERCHANTABILITY,
23
FITNESS FOR  A PARTICULAR PURPOSE AND  NONINFRINGEMENT. IN NO EVENT  SHALL THE
24
AUTHORS  OR COPYRIGHT  HOLDERS  BE  LIABLE FOR  ANY  CLAIM,  DAMAGES OR  OTHER
25
LIABILITY, WHETHER IN AN ACTION OF  CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
OUT OF OR IN CONNECTION WITH THE SOFTWARE  OR THE USE OR OTHER DEALINGS IN THE
27
SOFTWARE.
28
*/
29
30
#ifndef NLOHMANN_JSON_HPP
31
#define NLOHMANN_JSON_HPP
32
33
#define NLOHMANN_JSON_VERSION_MAJOR 3
34
#define NLOHMANN_JSON_VERSION_MINOR 2
35
#define NLOHMANN_JSON_VERSION_PATCH 0
36
37
#include <algorithm> // all_of, find, for_each
38
#include <cassert> // assert
39
#include <ciso646> // and, not, or
40
#include <cstddef> // nullptr_t, ptrdiff_t, size_t
41
#include <functional> // hash, less
42
#include <initializer_list> // initializer_list
43
#include <iosfwd> // istream, ostream
44
#include <iterator> // iterator_traits, random_access_iterator_tag
45
#include <numeric> // accumulate
46
#include <string> // string, stoi, to_string
47
#include <utility> // declval, forward, move, pair, swap
48
49
// #include <nlohmann/json_fwd.hpp>
50
#ifndef NLOHMANN_JSON_FWD_HPP
51
#define NLOHMANN_JSON_FWD_HPP
52
53
#include <cstdint> // int64_t, uint64_t
54
#include <map> // map
55
#include <memory> // allocator
56
#include <string> // string
57
#include <vector> // vector
58
59
/*!
60
@brief namespace for Niels Lohmann
61
@see https://github.com/nlohmann
62
@since version 1.0.0
63
*/
64
namespace nlohmann
65
{
66
/*!
67
@brief default JSONSerializer template argument
68
69
This serializer ignores the template arguments and uses ADL
70
([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
71
for serialization.
72
*/
73
template<typename T = void, typename SFINAE = void>
74
struct adl_serializer;
75
76
template<template<typename U, typename V, typename... Args> class ObjectType =
77
         std::map,
78
         template<typename U, typename... Args> class ArrayType = std::vector,
79
         class StringType = std::string, class BooleanType = bool,
80
         class NumberIntegerType = std::int64_t,
81
         class NumberUnsignedType = std::uint64_t,
82
         class NumberFloatType = double,
83
         template<typename U> class AllocatorType = std::allocator,
84
         template<typename T, typename SFINAE = void> class JSONSerializer =
85
         adl_serializer>
86
class basic_json;
87
88
/*!
89
@brief JSON Pointer
90
91
A JSON pointer defines a string syntax for identifying a specific value
92
within a JSON document. It can be used with functions `at` and
93
`operator[]`. Furthermore, JSON pointers are the base for JSON patches.
94
95
@sa [RFC 6901](https://tools.ietf.org/html/rfc6901)
96
97
@since version 2.0.0
98
*/
99
template<typename BasicJsonType>
100
class json_pointer;
101
102
/*!
103
@brief default JSON class
104
105
This type is the default specialization of the @ref basic_json class which
106
uses the standard template types.
107
108
@since version 1.0.0
109
*/
110
using json = basic_json<>;
111
}
112
113
#endif
114
115
// #include <nlohmann/detail/macro_scope.hpp>
116
117
118
// This file contains all internal macro definitions
119
// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
120
121
// exclude unsupported compilers
122
#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
123
    #if defined(__clang__)
124
        #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
125
            #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
126
        #endif
127
    #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
128
        #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40900
129
            #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
130
        #endif
131
    #endif
132
#endif
133
134
// disable float-equal warnings on GCC/clang
135
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
136
    #pragma GCC diagnostic push
137
    #pragma GCC diagnostic ignored "-Wfloat-equal"
138
#endif
139
140
// disable documentation warnings on clang
141
#if defined(__clang__)
142
    #pragma GCC diagnostic push
143
    #pragma GCC diagnostic ignored "-Wdocumentation"
144
#endif
145
146
// allow for portable deprecation warnings
147
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
148
    #define JSON_DEPRECATED __attribute__((deprecated))
149
#elif defined(_MSC_VER)
150
    #define JSON_DEPRECATED __declspec(deprecated)
151
#else
152
    #define JSON_DEPRECATED
153
#endif
154
155
// allow to disable exceptions
156
#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
157
2
    #define JSON_THROW(exception) throw exception
158
12.6k
    #define JSON_TRY try
159
    #define JSON_CATCH(exception) catch(exception)
160
    #define JSON_INTERNAL_CATCH(exception) catch(exception)
161
#else
162
    #define JSON_THROW(exception) std::abort()
163
    #define JSON_TRY if(true)
164
    #define JSON_CATCH(exception) if(false)
165
    #define JSON_INTERNAL_CATCH(exception) if(false)
166
#endif
167
168
// override exception macros
169
#if defined(JSON_THROW_USER)
170
    #undef JSON_THROW
171
    #define JSON_THROW JSON_THROW_USER
172
#endif
173
#if defined(JSON_TRY_USER)
174
    #undef JSON_TRY
175
    #define JSON_TRY JSON_TRY_USER
176
#endif
177
#if defined(JSON_CATCH_USER)
178
    #undef JSON_CATCH
179
    #define JSON_CATCH JSON_CATCH_USER
180
    #undef JSON_INTERNAL_CATCH
181
    #define JSON_INTERNAL_CATCH JSON_CATCH_USER
182
#endif
183
#if defined(JSON_INTERNAL_CATCH_USER)
184
    #undef JSON_INTERNAL_CATCH
185
    #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
186
#endif
187
188
// manual branch prediction
189
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
190
9.05M
    #define JSON_LIKELY(x)      __builtin_expect(!!(x), 1)
191
1.17M
    #define JSON_UNLIKELY(x)    __builtin_expect(!!(x), 0)
192
#else
193
    #define JSON_LIKELY(x)      x
194
    #define JSON_UNLIKELY(x)    x
195
#endif
196
197
// C++ language standard detection
198
#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
199
    #define JSON_HAS_CPP_17
200
    #define JSON_HAS_CPP_14
201
#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
202
    #define JSON_HAS_CPP_14
203
#endif
204
205
// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
206
// may be removed in the future once the class is split.
207
208
#define NLOHMANN_BASIC_JSON_TPL_DECLARATION                                \
209
    template<template<typename, typename, typename...> class ObjectType,   \
210
             template<typename, typename...> class ArrayType,              \
211
             class StringType, class BooleanType, class NumberIntegerType, \
212
             class NumberUnsignedType, class NumberFloatType,              \
213
             template<typename> class AllocatorType,                       \
214
             template<typename, typename = void> class JSONSerializer>
215
216
#define NLOHMANN_BASIC_JSON_TPL                                            \
217
    basic_json<ObjectType, ArrayType, StringType, BooleanType,             \
218
    NumberIntegerType, NumberUnsignedType, NumberFloatType,                \
219
    AllocatorType, JSONSerializer>
220
221
// #include <nlohmann/detail/meta/cpp_future.hpp>
222
223
224
#include <ciso646> // not
225
#include <cstddef> // size_t
226
#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
227
228
namespace nlohmann
229
{
230
namespace detail
231
{
232
// alias templates to reduce boilerplate
233
template<bool B, typename T = void>
234
using enable_if_t = typename std::enable_if<B, T>::type;
235
236
template<typename T>
237
using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
238
239
// implementation of C++14 index_sequence and affiliates
240
// source: https://stackoverflow.com/a/32223343
241
template<std::size_t... Ints>
242
struct index_sequence
243
{
244
    using type = index_sequence;
245
    using value_type = std::size_t;
246
    static constexpr std::size_t size() noexcept
247
    {
248
        return sizeof...(Ints);
249
    }
250
};
251
252
template<class Sequence1, class Sequence2>
253
struct merge_and_renumber;
254
255
template<std::size_t... I1, std::size_t... I2>
256
struct merge_and_renumber<index_sequence<I1...>, index_sequence<I2...>>
257
        : index_sequence < I1..., (sizeof...(I1) + I2)... > {};
258
259
template<std::size_t N>
260
struct make_index_sequence
261
    : merge_and_renumber < typename make_index_sequence < N / 2 >::type,
262
      typename make_index_sequence < N - N / 2 >::type > {};
263
264
template<> struct make_index_sequence<0> : index_sequence<> {};
265
template<> struct make_index_sequence<1> : index_sequence<0> {};
266
267
template<typename... Ts>
268
using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
269
270
// dispatch utility (taken from ranges-v3)
271
template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
272
template<> struct priority_tag<0> {};
273
274
// taken from ranges-v3
275
template<typename T>
276
struct static_const
277
{
278
    static constexpr T value{};
279
};
280
281
template<typename T>
282
constexpr T static_const<T>::value;
283
}
284
}
285
286
// #include <nlohmann/detail/meta/type_traits.hpp>
287
288
289
#include <ciso646> // not
290
#include <limits> // numeric_limits
291
#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
292
#include <utility> // declval
293
294
// #include <nlohmann/json_fwd.hpp>
295
296
// #include <nlohmann/detail/meta/cpp_future.hpp>
297
298
// #include <nlohmann/detail/meta/detected.hpp>
299
300
301
#include <type_traits>
302
303
// #include <nlohmann/detail/meta/void_t.hpp>
304
305
306
namespace nlohmann
307
{
308
namespace detail
309
{
310
template <typename ...Ts> struct make_void
311
{
312
    using type = void;
313
};
314
template <typename ...Ts> using void_t = typename make_void<Ts...>::type;
315
}
316
}
317
318
319
// http://en.cppreference.com/w/cpp/experimental/is_detected
320
namespace nlohmann
321
{
322
namespace detail
323
{
324
struct nonesuch
325
{
326
    nonesuch() = delete;
327
    ~nonesuch() = delete;
328
    nonesuch(nonesuch const&) = delete;
329
    void operator=(nonesuch const&) = delete;
330
};
331
332
template <class Default,
333
          class AlwaysVoid,
334
          template <class...> class Op,
335
          class... Args>
336
struct detector
337
{
338
    using value_t = std::false_type;
339
    using type = Default;
340
};
341
342
template <class Default, template <class...> class Op, class... Args>
343
struct detector<Default, void_t<Op<Args...>>, Op, Args...>
344
{
345
    using value_t = std::true_type;
346
    using type = Op<Args...>;
347
};
348
349
template <template <class...> class Op, class... Args>
350
using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
351
352
template <template <class...> class Op, class... Args>
353
using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
354
355
template <class Default, template <class...> class Op, class... Args>
356
using detected_or = detector<Default, void, Op, Args...>;
357
358
template <class Default, template <class...> class Op, class... Args>
359
using detected_or_t = typename detected_or<Default, Op, Args...>::type;
360
361
template <class Expected, template <class...> class Op, class... Args>
362
using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
363
364
template <class To, template <class...> class Op, class... Args>
365
using is_detected_convertible =
366
    std::is_convertible<detected_t<Op, Args...>, To>;
367
}
368
}
369
370
// #include <nlohmann/detail/macro_scope.hpp>
371
372
373
namespace nlohmann
374
{
375
/*!
376
@brief detail namespace with internal helper functions
377
378
This namespace collects functions that should not be exposed,
379
implementations of some @ref basic_json methods, and meta-programming helpers.
380
381
@since version 2.1.0
382
*/
383
namespace detail
384
{
385
/////////////
386
// helpers //
387
/////////////
388
389
template<typename> struct is_basic_json : std::false_type {};
390
391
NLOHMANN_BASIC_JSON_TPL_DECLARATION
392
struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
393
394
//////////////////////////
395
// aliases for detected //
396
//////////////////////////
397
398
template <typename T>
399
using mapped_type_t = typename T::mapped_type;
400
401
template <typename T>
402
using key_type_t = typename T::key_type;
403
404
template <typename T>
405
using value_type_t = typename T::value_type;
406
407
template <typename T>
408
using difference_type_t = typename T::difference_type;
409
410
template <typename T>
411
using pointer_t = typename T::pointer;
412
413
template <typename T>
414
using reference_t = typename T::reference;
415
416
template <typename T>
417
using iterator_category_t = typename T::iterator_category;
418
419
template <typename T>
420
using iterator_t = typename T::iterator;
421
422
template <typename T, typename... Args>
423
using to_json_function = decltype(T::to_json(std::declval<Args>()...));
424
425
template <typename T, typename... Args>
426
using from_json_function = decltype(T::from_json(std::declval<Args>()...));
427
428
///////////////////
429
// is_ functions //
430
///////////////////
431
432
template <typename T, typename = void>
433
struct is_iterator_traits : std::false_type {};
434
435
template <typename T>
436
struct is_iterator_traits<std::iterator_traits<T>>
437
{
438
  private:
439
    using traits = std::iterator_traits<T>;
440
441
  public:
442
    static constexpr auto value =
443
        is_detected<value_type_t, traits>::value &&
444
        is_detected<difference_type_t, traits>::value &&
445
        is_detected<pointer_t, traits>::value &&
446
        is_detected<iterator_category_t, traits>::value &&
447
        is_detected<reference_t, traits>::value;
448
};
449
450
// source: https://stackoverflow.com/a/37193089/4116453
451
452
template <typename T, typename = void>
453
struct is_complete_type : std::false_type {};
454
455
template <typename T>
456
struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
457
458
template <typename BasicJsonType, typename CompatibleObjectType,
459
          typename = void>
460
struct is_compatible_object_type_impl : std::false_type {};
461
462
template <typename BasicJsonType, typename CompatibleObjectType>
463
struct is_compatible_object_type_impl <
464
    BasicJsonType, CompatibleObjectType,
465
    enable_if_t<is_detected<mapped_type_t, CompatibleObjectType>::value and
466
    is_detected<key_type_t, CompatibleObjectType>::value >>
467
{
468
469
    using object_t = typename BasicJsonType::object_t;
470
471
    // macOS's is_constructible does not play well with nonesuch...
472
    static constexpr bool value =
473
        std::is_constructible<typename object_t::key_type,
474
        typename CompatibleObjectType::key_type>::value and
475
        std::is_constructible<typename object_t::mapped_type,
476
        typename CompatibleObjectType::mapped_type>::value;
477
};
478
479
template <typename BasicJsonType, typename CompatibleObjectType>
480
struct is_compatible_object_type
481
    : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
482
483
template <typename BasicJsonType, typename CompatibleStringType,
484
          typename = void>
485
struct is_compatible_string_type_impl : std::false_type {};
486
487
template <typename BasicJsonType, typename CompatibleStringType>
488
struct is_compatible_string_type_impl <
489
    BasicJsonType, CompatibleStringType,
490
    enable_if_t<is_detected_exact<typename BasicJsonType::string_t::value_type,
491
    value_type_t, CompatibleStringType>::value >>
492
{
493
    static constexpr auto value =
494
        std::is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value;
495
};
496
497
template <typename BasicJsonType, typename CompatibleStringType>
498
struct is_compatible_string_type
499
    : is_compatible_string_type_impl<BasicJsonType, CompatibleStringType> {};
500
501
template <typename BasicJsonType, typename CompatibleArrayType, typename = void>
502
struct is_compatible_array_type_impl : std::false_type {};
503
504
template <typename BasicJsonType, typename CompatibleArrayType>
505
struct is_compatible_array_type_impl <
506
    BasicJsonType, CompatibleArrayType,
507
    enable_if_t<is_detected<value_type_t, CompatibleArrayType>::value and
508
    is_detected<iterator_t, CompatibleArrayType>::value >>
509
{
510
    // This is needed because json_reverse_iterator has a ::iterator type...
511
    // Therefore it is detected as a CompatibleArrayType.
512
    // The real fix would be to have an Iterable concept.
513
    static constexpr bool value = not is_iterator_traits<std::iterator_traits<CompatibleArrayType>>::value;
514
};
515
516
template <typename BasicJsonType, typename CompatibleArrayType>
517
struct is_compatible_array_type
518
    : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
519
520
template <typename RealIntegerType, typename CompatibleNumberIntegerType,
521
          typename = void>
522
struct is_compatible_integer_type_impl : std::false_type {};
523
524
template <typename RealIntegerType, typename CompatibleNumberIntegerType>
525
struct is_compatible_integer_type_impl <
526
    RealIntegerType, CompatibleNumberIntegerType,
527
    enable_if_t<std::is_integral<RealIntegerType>::value and
528
    std::is_integral<CompatibleNumberIntegerType>::value and
529
    not std::is_same<bool, CompatibleNumberIntegerType>::value >>
530
{
531
    // is there an assert somewhere on overflows?
532
    using RealLimits = std::numeric_limits<RealIntegerType>;
533
    using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
534
535
    static constexpr auto value =
536
        std::is_constructible<RealIntegerType,
537
        CompatibleNumberIntegerType>::value and
538
        CompatibleLimits::is_integer and
539
        RealLimits::is_signed == CompatibleLimits::is_signed;
540
};
541
542
template <typename RealIntegerType, typename CompatibleNumberIntegerType>
543
struct is_compatible_integer_type
544
    : is_compatible_integer_type_impl<RealIntegerType,
545
      CompatibleNumberIntegerType> {};
546
547
// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
548
template<typename BasicJsonType, typename T>
549
struct has_from_json
550
{
551
    using serializer = typename BasicJsonType::template json_serializer<T, void>;
552
553
    static constexpr bool value =
554
        is_detected_exact<void, from_json_function, serializer,
555
        const BasicJsonType&, T&>::value;
556
};
557
558
// This trait checks if JSONSerializer<T>::from_json(json const&) exists
559
// this overload is used for non-default-constructible user-defined-types
560
template<typename BasicJsonType, typename T>
561
struct has_non_default_from_json
562
{
563
    using serializer = typename BasicJsonType::template json_serializer<T, void>;
564
565
    static constexpr bool value =
566
        is_detected_exact<T, from_json_function, serializer,
567
        const BasicJsonType&>::value;
568
};
569
570
// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
571
template<typename BasicJsonType, typename T>
572
struct has_to_json
573
{
574
    using serializer = typename BasicJsonType::template json_serializer<T, void>;
575
576
    static constexpr bool value =
577
        is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
578
        T>::value;
579
};
580
581
template <typename BasicJsonType, typename CompatibleType, typename = void>
582
struct is_compatible_type_impl: std::false_type {};
583
584
template <typename BasicJsonType, typename CompatibleType>
585
struct is_compatible_type_impl <
586
    BasicJsonType, CompatibleType,
587
    enable_if_t<is_complete_type<CompatibleType>::value >>
588
{
589
    static constexpr bool value =
590
        has_to_json<BasicJsonType, CompatibleType>::value;
591
};
592
593
template <typename BasicJsonType, typename CompatibleType>
594
struct is_compatible_type
595
    : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
596
}
597
}
598
599
// #include <nlohmann/detail/exceptions.hpp>
600
601
602
#include <exception> // exception
603
#include <stdexcept> // runtime_error
604
#include <string> // to_string
605
606
namespace nlohmann
607
{
608
namespace detail
609
{
610
////////////////
611
// exceptions //
612
////////////////
613
614
/*!
615
@brief general exception of the @ref basic_json class
616
617
This class is an extension of `std::exception` objects with a member @a id for
618
exception ids. It is used as the base class for all exceptions thrown by the
619
@ref basic_json class. This class can hence be used as "wildcard" to catch
620
exceptions.
621
622
Subclasses:
623
- @ref parse_error for exceptions indicating a parse error
624
- @ref invalid_iterator for exceptions indicating errors with iterators
625
- @ref type_error for exceptions indicating executing a member function with
626
                  a wrong type
627
- @ref out_of_range for exceptions indicating access out of the defined range
628
- @ref other_error for exceptions indicating other library errors
629
630
@internal
631
@note To have nothrow-copy-constructible exceptions, we internally use
632
      `std::runtime_error` which can cope with arbitrary-length error messages.
633
      Intermediate strings are built with static functions and then passed to
634
      the actual constructor.
635
@endinternal
636
637
@liveexample{The following code shows how arbitrary library exceptions can be
638
caught.,exception}
639
640
@since version 3.0.0
641
*/
642
class exception : public std::exception
643
{
644
  public:
645
    /// returns the explanatory string
646
    const char* what() const noexcept override
647
0
    {
648
0
        return m.what();
649
0
    }
650
651
    /// the id of the exception
652
    const int id;
653
654
  protected:
655
2
    exception(int id_, const char* what_arg) : id(id_), m(what_arg) {}
656
657
    static std::string name(const std::string& ename, int id_)
658
2
    {
659
2
        return "[json.exception." + ename + "." + std::to_string(id_) + "] ";
660
2
    }
661
662
  private:
663
    /// an exception object as storage for error messages
664
    std::runtime_error m;
665
};
666
667
/*!
668
@brief exception indicating a parse error
669
670
This exception is thrown by the library when a parse error occurs. Parse errors
671
can occur during the deserialization of JSON text, CBOR, MessagePack, as well
672
as when using JSON Patch.
673
674
Member @a byte holds the byte index of the last read character in the input
675
file.
676
677
Exceptions have ids 1xx.
678
679
name / id                      | example message | description
680
------------------------------ | --------------- | -------------------------
681
json.exception.parse_error.101 | parse error at 2: unexpected end of input; expected string literal | This error indicates a syntax error while deserializing a JSON text. The error message describes that an unexpected token (character) was encountered, and the member @a byte indicates the error position.
682
json.exception.parse_error.102 | parse error at 14: missing or wrong low surrogate | JSON uses the `\uxxxx` format to describe Unicode characters. Code points above above 0xFFFF are split into two `\uxxxx` entries ("surrogate pairs"). This error indicates that the surrogate pair is incomplete or contains an invalid code point.
683
json.exception.parse_error.103 | parse error: code points above 0x10FFFF are invalid | Unicode supports code points up to 0x10FFFF. Code points above 0x10FFFF are invalid.
684
json.exception.parse_error.104 | parse error: JSON patch must be an array of objects | [RFC 6902](https://tools.ietf.org/html/rfc6902) requires a JSON Patch document to be a JSON document that represents an array of objects.
685
json.exception.parse_error.105 | parse error: operation must have string member 'op' | An operation of a JSON Patch document must contain exactly one "op" member, whose value indicates the operation to perform. Its value must be one of "add", "remove", "replace", "move", "copy", or "test"; other values are errors.
686
json.exception.parse_error.106 | parse error: array index '01' must not begin with '0' | An array index in a JSON Pointer ([RFC 6901](https://tools.ietf.org/html/rfc6901)) may be `0` or any number without a leading `0`.
687
json.exception.parse_error.107 | parse error: JSON pointer must be empty or begin with '/' - was: 'foo' | A JSON Pointer must be a Unicode string containing a sequence of zero or more reference tokens, each prefixed by a `/` character.
688
json.exception.parse_error.108 | parse error: escape character '~' must be followed with '0' or '1' | In a JSON Pointer, only `~0` and `~1` are valid escape sequences.
689
json.exception.parse_error.109 | parse error: array index 'one' is not a number | A JSON Pointer array index must be a number.
690
json.exception.parse_error.110 | parse error at 1: cannot read 2 bytes from vector | When parsing CBOR or MessagePack, the byte vector ends before the complete value has been read.
691
json.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xF8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read.
692
json.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been read.
693
694
@note For an input with n bytes, 1 is the index of the first character and n+1
695
      is the index of the terminating null byte or the end of file. This also
696
      holds true when reading a byte vector (CBOR or MessagePack).
697
698
@liveexample{The following code shows how a `parse_error` exception can be
699
caught.,parse_error}
700
701
@sa @ref exception for the base class of the library exceptions
702
@sa @ref invalid_iterator for exceptions indicating errors with iterators
703
@sa @ref type_error for exceptions indicating executing a member function with
704
                    a wrong type
705
@sa @ref out_of_range for exceptions indicating access out of the defined range
706
@sa @ref other_error for exceptions indicating other library errors
707
708
@since version 3.0.0
709
*/
710
class parse_error : public exception
711
{
712
  public:
713
    /*!
714
    @brief create a parse error exception
715
    @param[in] id_       the id of the exception
716
    @param[in] byte_     the byte index where the error occurred (or 0 if the
717
                         position cannot be determined)
718
    @param[in] what_arg  the explanatory string
719
    @return parse_error object
720
    */
721
    static parse_error create(int id_, std::size_t byte_, const std::string& what_arg)
722
1
    {
723
1
        std::string w = exception::name("parse_error", id_) + "parse error" +
724
1
                        (byte_ != 0 ? (" at " + std::to_string(byte_)) : "") +
725
1
                        ": " + what_arg;
726
1
        return parse_error(id_, byte_, w.c_str());
727
1
    }
728
729
    /*!
730
    @brief byte index of the parse error
731
732
    The byte index of the last read character in the input file.
733
734
    @note For an input with n bytes, 1 is the index of the first character and
735
          n+1 is the index of the terminating null byte or the end of file.
736
          This also holds true when reading a byte vector (CBOR or MessagePack).
737
    */
738
    const std::size_t byte;
739
740
  private:
741
    parse_error(int id_, std::size_t byte_, const char* what_arg)
742
1
        : exception(id_, what_arg), byte(byte_) {}
743
};
744
745
/*!
746
@brief exception indicating errors with iterators
747
748
This exception is thrown if iterators passed to a library function do not match
749
the expected semantics.
750
751
Exceptions have ids 2xx.
752
753
name / id                           | example message | description
754
----------------------------------- | --------------- | -------------------------
755
json.exception.invalid_iterator.201 | iterators are not compatible | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid.
756
json.exception.invalid_iterator.202 | iterator does not fit current value | In an erase or insert function, the passed iterator @a pos does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion.
757
json.exception.invalid_iterator.203 | iterators do not fit current value | Either iterator passed to function @ref erase(IteratorType first, IteratorType last) does not belong to the JSON value from which values shall be erased. It hence does not define a valid range to delete values from.
758
json.exception.invalid_iterator.204 | iterators out of range | When an iterator range for a primitive type (number, boolean, or string) is passed to a constructor or an erase function, this range has to be exactly (@ref begin(), @ref end()), because this is the only way the single stored value is expressed. All other ranges are invalid.
759
json.exception.invalid_iterator.205 | iterator out of range | When an iterator for a primitive type (number, boolean, or string) is passed to an erase function, the iterator has to be the @ref begin() iterator, because it is the only way to address the stored value. All other iterators are invalid.
760
json.exception.invalid_iterator.206 | cannot construct with iterators from null | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) belong to a JSON null value and hence to not define a valid range.
761
json.exception.invalid_iterator.207 | cannot use key() for non-object iterators | The key() member function can only be used on iterators belonging to a JSON object, because other types do not have a concept of a key.
762
json.exception.invalid_iterator.208 | cannot use operator[] for object iterators | The operator[] to specify a concrete offset cannot be used on iterators belonging to a JSON object, because JSON objects are unordered.
763
json.exception.invalid_iterator.209 | cannot use offsets with object iterators | The offset operators (+, -, +=, -=) cannot be used on iterators belonging to a JSON object, because JSON objects are unordered.
764
json.exception.invalid_iterator.210 | iterators do not fit | The iterator range passed to the insert function are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid.
765
json.exception.invalid_iterator.211 | passed iterators may not belong to container | The iterator range passed to the insert function must not be a subrange of the container to insert to.
766
json.exception.invalid_iterator.212 | cannot compare iterators of different containers | When two iterators are compared, they must belong to the same container.
767
json.exception.invalid_iterator.213 | cannot compare order of object iterators | The order of object iterators cannot be compared, because JSON objects are unordered.
768
json.exception.invalid_iterator.214 | cannot get value | Cannot get value for iterator: Either the iterator belongs to a null value or it is an iterator to a primitive type (number, boolean, or string), but the iterator is different to @ref begin().
769
770
@liveexample{The following code shows how an `invalid_iterator` exception can be
771
caught.,invalid_iterator}
772
773
@sa @ref exception for the base class of the library exceptions
774
@sa @ref parse_error for exceptions indicating a parse error
775
@sa @ref type_error for exceptions indicating executing a member function with
776
                    a wrong type
777
@sa @ref out_of_range for exceptions indicating access out of the defined range
778
@sa @ref other_error for exceptions indicating other library errors
779
780
@since version 3.0.0
781
*/
782
class invalid_iterator : public exception
783
{
784
  public:
785
    static invalid_iterator create(int id_, const std::string& what_arg)
786
0
    {
787
0
        std::string w = exception::name("invalid_iterator", id_) + what_arg;
788
0
        return invalid_iterator(id_, w.c_str());
789
0
    }
790
791
  private:
792
    invalid_iterator(int id_, const char* what_arg)
793
0
        : exception(id_, what_arg) {}
794
};
795
796
/*!
797
@brief exception indicating executing a member function with a wrong type
798
799
This exception is thrown in case of a type error; that is, a library function is
800
executed on a JSON value whose type does not match the expected semantics.
801
802
Exceptions have ids 3xx.
803
804
name / id                     | example message | description
805
----------------------------- | --------------- | -------------------------
806
json.exception.type_error.301 | cannot create object from initializer list | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead.
807
json.exception.type_error.302 | type must be object, but is array | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types.
808
json.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t&.
809
json.exception.type_error.304 | cannot use at() with string | The @ref at() member functions can only be executed for certain JSON types.
810
json.exception.type_error.305 | cannot use operator[] with string | The @ref operator[] member functions can only be executed for certain JSON types.
811
json.exception.type_error.306 | cannot use value() with string | The @ref value() member functions can only be executed for certain JSON types.
812
json.exception.type_error.307 | cannot use erase() with string | The @ref erase() member functions can only be executed for certain JSON types.
813
json.exception.type_error.308 | cannot use push_back() with string | The @ref push_back() and @ref operator+= member functions can only be executed for certain JSON types.
814
json.exception.type_error.309 | cannot use insert() with | The @ref insert() member functions can only be executed for certain JSON types.
815
json.exception.type_error.310 | cannot use swap() with number | The @ref swap() member functions can only be executed for certain JSON types.
816
json.exception.type_error.311 | cannot use emplace_back() with string | The @ref emplace_back() member function can only be executed for certain JSON types.
817
json.exception.type_error.312 | cannot use update() with string | The @ref update() member functions can only be executed for certain JSON types.
818
json.exception.type_error.313 | invalid value to unflatten | The @ref unflatten function converts an object whose keys are JSON Pointers back into an arbitrary nested JSON value. The JSON Pointers must not overlap, because then the resulting value would not be well defined.
819
json.exception.type_error.314 | only objects can be unflattened | The @ref unflatten function only works for an object whose keys are JSON Pointers.
820
json.exception.type_error.315 | values in object must be primitive | The @ref unflatten function only works for an object whose keys are JSON Pointers and whose values are primitive.
821
json.exception.type_error.316 | invalid UTF-8 byte at index 10: 0x7E | The @ref dump function only works with UTF-8 encoded strings; that is, if you assign a `std::string` to a JSON value, make sure it is UTF-8 encoded. |
822
823
@liveexample{The following code shows how a `type_error` exception can be
824
caught.,type_error}
825
826
@sa @ref exception for the base class of the library exceptions
827
@sa @ref parse_error for exceptions indicating a parse error
828
@sa @ref invalid_iterator for exceptions indicating errors with iterators
829
@sa @ref out_of_range for exceptions indicating access out of the defined range
830
@sa @ref other_error for exceptions indicating other library errors
831
832
@since version 3.0.0
833
*/
834
class type_error : public exception
835
{
836
  public:
837
    static type_error create(int id_, const std::string& what_arg)
838
0
    {
839
0
        std::string w = exception::name("type_error", id_) + what_arg;
840
0
        return type_error(id_, w.c_str());
841
0
    }
842
843
  private:
844
0
    type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
845
};
846
847
/*!
848
@brief exception indicating access out of the defined range
849
850
This exception is thrown in case a library function is called on an input
851
parameter that exceeds the expected range, for instance in case of array
852
indices or nonexisting object keys.
853
854
Exceptions have ids 4xx.
855
856
name / id                       | example message | description
857
------------------------------- | --------------- | -------------------------
858
json.exception.out_of_range.401 | array index 3 is out of range | The provided array index @a i is larger than @a size-1.
859
json.exception.out_of_range.402 | array index '-' (3) is out of range | The special array index `-` in a JSON Pointer never describes a valid element of the array, but the index past the end. That is, it can only be used to add elements at this position, but not to read it.
860
json.exception.out_of_range.403 | key 'foo' not found | The provided key was not found in the JSON object.
861
json.exception.out_of_range.404 | unresolved reference token 'foo' | A reference token in a JSON Pointer could not be resolved.
862
json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value.
863
json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF.
864
json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON only supports integers numbers up to 9223372036854775807. |
865
json.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. |
866
867
@liveexample{The following code shows how an `out_of_range` exception can be
868
caught.,out_of_range}
869
870
@sa @ref exception for the base class of the library exceptions
871
@sa @ref parse_error for exceptions indicating a parse error
872
@sa @ref invalid_iterator for exceptions indicating errors with iterators
873
@sa @ref type_error for exceptions indicating executing a member function with
874
                    a wrong type
875
@sa @ref other_error for exceptions indicating other library errors
876
877
@since version 3.0.0
878
*/
879
class out_of_range : public exception
880
{
881
  public:
882
    static out_of_range create(int id_, const std::string& what_arg)
883
1
    {
884
1
        std::string w = exception::name("out_of_range", id_) + what_arg;
885
1
        return out_of_range(id_, w.c_str());
886
1
    }
887
888
  private:
889
1
    out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
890
};
891
892
/*!
893
@brief exception indicating other library errors
894
895
This exception is thrown in case of errors that cannot be classified with the
896
other exception types.
897
898
Exceptions have ids 5xx.
899
900
name / id                      | example message | description
901
------------------------------ | --------------- | -------------------------
902
json.exception.other_error.501 | unsuccessful: {"op":"test","path":"/baz", "value":"bar"} | A JSON Patch operation 'test' failed. The unsuccessful operation is also printed.
903
904
@sa @ref exception for the base class of the library exceptions
905
@sa @ref parse_error for exceptions indicating a parse error
906
@sa @ref invalid_iterator for exceptions indicating errors with iterators
907
@sa @ref type_error for exceptions indicating executing a member function with
908
                    a wrong type
909
@sa @ref out_of_range for exceptions indicating access out of the defined range
910
911
@liveexample{The following code shows how an `other_error` exception can be
912
caught.,other_error}
913
914
@since version 3.0.0
915
*/
916
class other_error : public exception
917
{
918
  public:
919
    static other_error create(int id_, const std::string& what_arg)
920
0
    {
921
0
        std::string w = exception::name("other_error", id_) + what_arg;
922
0
        return other_error(id_, w.c_str());
923
0
    }
924
925
  private:
926
0
    other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
927
};
928
}
929
}
930
931
// #include <nlohmann/detail/value_t.hpp>
932
933
934
#include <array> // array
935
#include <ciso646> // and
936
#include <cstddef> // size_t
937
#include <cstdint> // uint8_t
938
939
namespace nlohmann
940
{
941
namespace detail
942
{
943
///////////////////////////
944
// JSON type enumeration //
945
///////////////////////////
946
947
/*!
948
@brief the JSON type enumeration
949
950
This enumeration collects the different JSON types. It is internally used to
951
distinguish the stored values, and the functions @ref basic_json::is_null(),
952
@ref basic_json::is_object(), @ref basic_json::is_array(),
953
@ref basic_json::is_string(), @ref basic_json::is_boolean(),
954
@ref basic_json::is_number() (with @ref basic_json::is_number_integer(),
955
@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()),
956
@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and
957
@ref basic_json::is_structured() rely on it.
958
959
@note There are three enumeration entries (number_integer, number_unsigned, and
960
number_float), because the library distinguishes these three types for numbers:
961
@ref basic_json::number_unsigned_t is used for unsigned integers,
962
@ref basic_json::number_integer_t is used for signed integers, and
963
@ref basic_json::number_float_t is used for floating-point numbers or to
964
approximate integers which do not fit in the limits of their respective type.
965
966
@sa @ref basic_json::basic_json(const value_t value_type) -- create a JSON
967
value with the default value for a given type
968
969
@since version 1.0.0
970
*/
971
enum class value_t : std::uint8_t
972
{
973
    null,             ///< null value
974
    object,           ///< object (unordered set of name/value pairs)
975
    array,            ///< array (ordered collection of values)
976
    string,           ///< string value
977
    boolean,          ///< boolean value
978
    number_integer,   ///< number value (signed integer)
979
    number_unsigned,  ///< number value (unsigned integer)
980
    number_float,     ///< number value (floating-point)
981
    discarded         ///< discarded by the the parser callback function
982
};
983
984
/*!
985
@brief comparison operator for JSON types
986
987
Returns an ordering that is similar to Python:
988
- order: null < boolean < number < object < array < string
989
- furthermore, each type is not smaller than itself
990
- discarded values are not comparable
991
992
@since version 1.0.0
993
*/
994
inline bool operator<(const value_t lhs, const value_t rhs) noexcept
995
0
{
996
0
    static constexpr std::array<std::uint8_t, 8> order = {{
997
0
            0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
998
0
            1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */
999
0
        }
1000
0
    };
1001
0
1002
0
    const auto l_index = static_cast<std::size_t>(lhs);
1003
0
    const auto r_index = static_cast<std::size_t>(rhs);
1004
0
    return l_index < order.size() and r_index < order.size() and order[l_index] < order[r_index];
1005
0
}
1006
}
1007
}
1008
1009
// #include <nlohmann/detail/conversions/from_json.hpp>
1010
1011
1012
#include <algorithm> // transform
1013
#include <array> // array
1014
#include <ciso646> // and, not
1015
#include <forward_list> // forward_list
1016
#include <iterator> // inserter, front_inserter, end
1017
#include <map> // map
1018
#include <string> // string
1019
#include <tuple> // tuple, make_tuple
1020
#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
1021
#include <unordered_map> // unordered_map
1022
#include <utility> // pair, declval
1023
#include <valarray> // valarray
1024
1025
// #include <nlohmann/detail/exceptions.hpp>
1026
1027
// #include <nlohmann/detail/macro_scope.hpp>
1028
1029
// #include <nlohmann/detail/meta/cpp_future.hpp>
1030
1031
// #include <nlohmann/detail/meta/type_traits.hpp>
1032
1033
// #include <nlohmann/detail/value_t.hpp>
1034
1035
1036
namespace nlohmann
1037
{
1038
namespace detail
1039
{
1040
template<typename BasicJsonType>
1041
void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
1042
{
1043
    if (JSON_UNLIKELY(not j.is_null()))
1044
    {
1045
        JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name())));
1046
    }
1047
    n = nullptr;
1048
}
1049
1050
// overloads for basic_json template parameters
1051
template<typename BasicJsonType, typename ArithmeticType,
1052
         enable_if_t<std::is_arithmetic<ArithmeticType>::value and
1053
                     not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
1054
                     int> = 0>
1055
void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
1056
148
{
1057
148
    switch (static_cast<value_t>(j))
1058
148
    {
1059
148
        case value_t::number_unsigned:
1060
0
        {
1061
0
            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
1062
0
            break;
1063
148
        }
1064
148
        case value_t::number_integer:
1065
0
        {
1066
0
            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
1067
0
            break;
1068
148
        }
1069
148
        case value_t::number_float:
1070
148
        {
1071
148
            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
1072
148
            break;
1073
148
        }
1074
148
1075
148
        default:
1076
0
            JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name())));
1077
148
    }
1078
148
}
1079
1080
template<typename BasicJsonType>
1081
void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
1082
2
{
1083
2
    if (JSON_UNLIKELY(not j.is_boolean()))
1084
2
    {
1085
0
        JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name())));
1086
0
    }
1087
2
    b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
1088
2
}
1089
1090
template<typename BasicJsonType>
1091
void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
1092
11.4k
{
1093
11.4k
    if (JSON_UNLIKELY(not j.is_string()))
1094
11.4k
    {
1095
0
        JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
1096
0
    }
1097
11.4k
    s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
1098
11.4k
}
1099
1100
template <
1101
    typename BasicJsonType, typename CompatibleStringType,
1102
    enable_if_t <
1103
        is_compatible_string_type<BasicJsonType, CompatibleStringType>::value and
1104
        not std::is_same<typename BasicJsonType::string_t,
1105
                         CompatibleStringType>::value,
1106
        int > = 0 >
1107
void from_json(const BasicJsonType& j, CompatibleStringType& s)
1108
{
1109
    if (JSON_UNLIKELY(not j.is_string()))
1110
    {
1111
        JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
1112
    }
1113
1114
    s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
1115
}
1116
1117
template<typename BasicJsonType>
1118
void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
1119
148
{
1120
148
    get_arithmetic_value(j, val);
1121
148
}
1122
1123
template<typename BasicJsonType>
1124
void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
1125
{
1126
    get_arithmetic_value(j, val);
1127
}
1128
1129
template<typename BasicJsonType>
1130
void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
1131
{
1132
    get_arithmetic_value(j, val);
1133
}
1134
1135
template<typename BasicJsonType, typename EnumType,
1136
         enable_if_t<std::is_enum<EnumType>::value, int> = 0>
1137
void from_json(const BasicJsonType& j, EnumType& e)
1138
{
1139
    typename std::underlying_type<EnumType>::type val;
1140
    get_arithmetic_value(j, val);
1141
    e = static_cast<EnumType>(val);
1142
}
1143
1144
// forward_list doesn't have an insert method
1145
template<typename BasicJsonType, typename T, typename Allocator,
1146
         enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>
1147
void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
1148
{
1149
    if (JSON_UNLIKELY(not j.is_array()))
1150
    {
1151
        JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
1152
    }
1153
    std::transform(j.rbegin(), j.rend(),
1154
                   std::front_inserter(l), [](const BasicJsonType & i)
1155
    {
1156
        return i.template get<T>();
1157
    });
1158
}
1159
1160
// valarray doesn't have an insert method
1161
template<typename BasicJsonType, typename T,
1162
         enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>
1163
void from_json(const BasicJsonType& j, std::valarray<T>& l)
1164
{
1165
    if (JSON_UNLIKELY(not j.is_array()))
1166
    {
1167
        JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
1168
    }
1169
    l.resize(j.size());
1170
    std::copy(j.m_value.array->begin(), j.m_value.array->end(), std::begin(l));
1171
}
1172
1173
template<typename BasicJsonType>
1174
void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
1175
{
1176
    arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
1177
}
1178
1179
template <typename BasicJsonType, typename T, std::size_t N>
1180
auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
1181
                          priority_tag<2> /*unused*/)
1182
-> decltype(j.template get<T>(), void())
1183
{
1184
    for (std::size_t i = 0; i < N; ++i)
1185
    {
1186
        arr[i] = j.at(i).template get<T>();
1187
    }
1188
}
1189
1190
template<typename BasicJsonType, typename CompatibleArrayType>
1191
auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<1> /*unused*/)
1192
-> decltype(
1193
    arr.reserve(std::declval<typename CompatibleArrayType::size_type>()),
1194
    j.template get<typename CompatibleArrayType::value_type>(),
1195
    void())
1196
{
1197
    using std::end;
1198
1199
    arr.reserve(j.size());
1200
    std::transform(j.begin(), j.end(),
1201
                   std::inserter(arr, end(arr)), [](const BasicJsonType & i)
1202
    {
1203
        // get<BasicJsonType>() returns *this, this won't call a from_json
1204
        // method when value_type is BasicJsonType
1205
        return i.template get<typename CompatibleArrayType::value_type>();
1206
    });
1207
}
1208
1209
template <typename BasicJsonType, typename CompatibleArrayType>
1210
void from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr,
1211
                          priority_tag<0> /*unused*/)
1212
{
1213
    using std::end;
1214
1215
    std::transform(
1216
        j.begin(), j.end(), std::inserter(arr, end(arr)),
1217
        [](const BasicJsonType & i)
1218
    {
1219
        // get<BasicJsonType>() returns *this, this won't call a from_json
1220
        // method when value_type is BasicJsonType
1221
        return i.template get<typename CompatibleArrayType::value_type>();
1222
    });
1223
}
1224
1225
template <typename BasicJsonType, typename CompatibleArrayType,
1226
          enable_if_t <
1227
              is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value and
1228
              not is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value and
1229
              not is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value and
1230
              not is_basic_json<CompatibleArrayType>::value,
1231
              int > = 0 >
1232
1233
auto from_json(const BasicJsonType& j, CompatibleArrayType& arr)
1234
-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
1235
j.template get<typename CompatibleArrayType::value_type>(),
1236
void())
1237
{
1238
    if (JSON_UNLIKELY(not j.is_array()))
1239
    {
1240
        JSON_THROW(type_error::create(302, "type must be array, but is " +
1241
                                      std::string(j.type_name())));
1242
    }
1243
1244
    from_json_array_impl(j, arr, priority_tag<3> {});
1245
}
1246
1247
template<typename BasicJsonType, typename CompatibleObjectType,
1248
         enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value, int> = 0>
1249
void from_json(const BasicJsonType& j, CompatibleObjectType& obj)
1250
{
1251
    if (JSON_UNLIKELY(not j.is_object()))
1252
    {
1253
        JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name())));
1254
    }
1255
1256
    auto inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
1257
    using value_type = typename CompatibleObjectType::value_type;
1258
    std::transform(
1259
        inner_object->begin(), inner_object->end(),
1260
        std::inserter(obj, obj.begin()),
1261
        [](typename BasicJsonType::object_t::value_type const & p)
1262
    {
1263
        return value_type(p.first, p.second.template get<typename CompatibleObjectType::mapped_type>());
1264
    });
1265
}
1266
1267
// overload for arithmetic types, not chosen for basic_json template arguments
1268
// (BooleanType, etc..); note: Is it really necessary to provide explicit
1269
// overloads for boolean_t etc. in case of a custom BooleanType which is not
1270
// an arithmetic type?
1271
template<typename BasicJsonType, typename ArithmeticType,
1272
         enable_if_t <
1273
             std::is_arithmetic<ArithmeticType>::value and
1274
             not std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value and
1275
             not std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value and
1276
             not std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value and
1277
             not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
1278
             int> = 0>
1279
void from_json(const BasicJsonType& j, ArithmeticType& val)
1280
152
{
1281
152
    switch (static_cast<value_t>(j))
1282
152
    {
1283
152
        case value_t::number_unsigned:
1284
152
        {
1285
152
            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
1286
152
            break;
1287
152
        }
1288
152
        case value_t::number_integer:
1289
0
        {
1290
0
            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
1291
0
            break;
1292
152
        }
1293
152
        case value_t::number_float:
1294
0
        {
1295
0
            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
1296
0
            break;
1297
152
        }
1298
152
        case value_t::boolean:
1299
0
        {
1300
0
            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
1301
0
            break;
1302
152
        }
1303
152
1304
152
        default:
1305
0
            JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name())));
1306
152
    }
1307
152
}
1308
1309
template<typename BasicJsonType, typename A1, typename A2>
1310
void from_json(const BasicJsonType& j, std::pair<A1, A2>& p)
1311
{
1312
    p = {j.at(0).template get<A1>(), j.at(1).template get<A2>()};
1313
}
1314
1315
template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
1316
void from_json_tuple_impl(const BasicJsonType& j, Tuple& t, index_sequence<Idx...>)
1317
{
1318
    t = std::make_tuple(j.at(Idx).template get<typename std::tuple_element<Idx, Tuple>::type>()...);
1319
}
1320
1321
template<typename BasicJsonType, typename... Args>
1322
void from_json(const BasicJsonType& j, std::tuple<Args...>& t)
1323
{
1324
    from_json_tuple_impl(j, t, index_sequence_for<Args...> {});
1325
}
1326
1327
template <typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
1328
          typename = enable_if_t<not std::is_constructible<
1329
                                     typename BasicJsonType::string_t, Key>::value>>
1330
void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
1331
{
1332
    if (JSON_UNLIKELY(not j.is_array()))
1333
    {
1334
        JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
1335
    }
1336
    for (const auto& p : j)
1337
    {
1338
        if (JSON_UNLIKELY(not p.is_array()))
1339
        {
1340
            JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
1341
        }
1342
        m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
1343
    }
1344
}
1345
1346
template <typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
1347
          typename = enable_if_t<not std::is_constructible<
1348
                                     typename BasicJsonType::string_t, Key>::value>>
1349
void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
1350
{
1351
    if (JSON_UNLIKELY(not j.is_array()))
1352
    {
1353
        JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
1354
    }
1355
    for (const auto& p : j)
1356
    {
1357
        if (JSON_UNLIKELY(not p.is_array()))
1358
        {
1359
            JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
1360
        }
1361
        m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
1362
    }
1363
}
1364
1365
struct from_json_fn
1366
{
1367
    template<typename BasicJsonType, typename T>
1368
    auto operator()(const BasicJsonType& j, T& val) const
1369
    noexcept(noexcept(from_json(j, val)))
1370
    -> decltype(from_json(j, val), void())
1371
11.7k
    {
1372
11.7k
        return from_json(j, val);
1373
11.7k
    }
_ZNK8nlohmann6detail12from_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEbEEDTcmcl9from_jsonfp_fp0_Ecvv_EERKT_RT0_
Line
Count
Source
1371
2
    {
1372
2
        return from_json(j, val);
1373
2
    }
_ZNK8nlohmann6detail12from_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEESB_EEDTcmcl9from_jsonfp_fp0_Ecvv_EERKT_RT0_
Line
Count
Source
1371
11.4k
    {
1372
11.4k
        return from_json(j, val);
1373
11.4k
    }
_ZNK8nlohmann6detail12from_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEiEEDTcmcl9from_jsonfp_fp0_Ecvv_EERKT_RT0_
Line
Count
Source
1371
152
    {
1372
152
        return from_json(j, val);
1373
152
    }
_ZNK8nlohmann6detail12from_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEdEEDTcmcl9from_jsonfp_fp0_Ecvv_EERKT_RT0_
Line
Count
Source
1371
148
    {
1372
148
        return from_json(j, val);
1373
148
    }
1374
};
1375
}
1376
1377
/// namespace to hold default `from_json` function
1378
/// to see why this is required:
1379
/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
1380
namespace
1381
{
1382
constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::value;
1383
}
1384
}
1385
1386
// #include <nlohmann/detail/conversions/to_json.hpp>
1387
1388
1389
#include <ciso646> // or, and, not
1390
#include <iterator> // begin, end
1391
#include <tuple> // tuple, get
1392
#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
1393
#include <utility> // move, forward, declval, pair
1394
#include <valarray> // valarray
1395
#include <vector> // vector
1396
1397
// #include <nlohmann/detail/meta/cpp_future.hpp>
1398
1399
// #include <nlohmann/detail/meta/type_traits.hpp>
1400
1401
// #include <nlohmann/detail/value_t.hpp>
1402
1403
// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
1404
1405
1406
#include <cstddef> // size_t
1407
#include <string> // string, to_string
1408
#include <iterator> // input_iterator_tag
1409
1410
// #include <nlohmann/detail/value_t.hpp>
1411
1412
1413
namespace nlohmann
1414
{
1415
namespace detail
1416
{
1417
/// proxy class for the items() function
1418
template<typename IteratorType> class iteration_proxy
1419
{
1420
  private:
1421
    /// helper class for iteration
1422
    class iteration_proxy_internal
1423
    {
1424
      public:
1425
        using difference_type = std::ptrdiff_t;
1426
        using value_type = iteration_proxy_internal;
1427
        using pointer = iteration_proxy_internal*;
1428
        using reference = iteration_proxy_internal&;
1429
        using iterator_category = std::input_iterator_tag;
1430
1431
      private:
1432
        /// the iterator
1433
        IteratorType anchor;
1434
        /// an index for arrays (used to create key names)
1435
        std::size_t array_index = 0;
1436
        /// last stringified array index
1437
        mutable std::size_t array_index_last = 0;
1438
        /// a string representation of the array index
1439
        mutable std::string array_index_str = "0";
1440
        /// an empty string (to return a reference for primitive values)
1441
        const std::string empty_str = "";
1442
1443
      public:
1444
        explicit iteration_proxy_internal(IteratorType it) noexcept : anchor(it) {}
1445
1446
        iteration_proxy_internal(const iteration_proxy_internal&) = default;
1447
        iteration_proxy_internal& operator=(const iteration_proxy_internal&) = default;
1448
1449
        /// dereference operator (needed for range-based for)
1450
        iteration_proxy_internal& operator*()
1451
        {
1452
            return *this;
1453
        }
1454
1455
        /// increment operator (needed for range-based for)
1456
        iteration_proxy_internal& operator++()
1457
        {
1458
            ++anchor;
1459
            ++array_index;
1460
1461
            return *this;
1462
        }
1463
1464
        /// equality operator (needed for InputIterator)
1465
        bool operator==(const iteration_proxy_internal& o) const noexcept
1466
        {
1467
            return anchor == o.anchor;
1468
        }
1469
1470
        /// inequality operator (needed for range-based for)
1471
        bool operator!=(const iteration_proxy_internal& o) const noexcept
1472
        {
1473
            return anchor != o.anchor;
1474
        }
1475
1476
        /// return key of the iterator
1477
        const std::string& key() const
1478
        {
1479
            assert(anchor.m_object != nullptr);
1480
1481
            switch (anchor.m_object->type())
1482
            {
1483
                // use integer array index as key
1484
                case value_t::array:
1485
                {
1486
                    if (array_index != array_index_last)
1487
                    {
1488
                        array_index_str = std::to_string(array_index);
1489
                        array_index_last = array_index;
1490
                    }
1491
                    return array_index_str;
1492
                }
1493
1494
                // use key from the object
1495
                case value_t::object:
1496
                    return anchor.key();
1497
1498
                // use an empty key for all primitive types
1499
                default:
1500
                    return empty_str;
1501
            }
1502
        }
1503
1504
        /// return value of the iterator
1505
        typename IteratorType::reference value() const
1506
        {
1507
            return anchor.value();
1508
        }
1509
    };
1510
1511
    /// the container to iterate
1512
    typename IteratorType::reference container;
1513
1514
  public:
1515
    /// construct iteration proxy from a container
1516
    explicit iteration_proxy(typename IteratorType::reference cont) noexcept
1517
        : container(cont) {}
1518
1519
    /// return iterator begin (needed for range-based for)
1520
    iteration_proxy_internal begin() noexcept
1521
    {
1522
        return iteration_proxy_internal(container.begin());
1523
    }
1524
1525
    /// return iterator end (needed for range-based for)
1526
    iteration_proxy_internal end() noexcept
1527
    {
1528
        return iteration_proxy_internal(container.end());
1529
    }
1530
};
1531
}
1532
}
1533
1534
1535
namespace nlohmann
1536
{
1537
namespace detail
1538
{
1539
//////////////////
1540
// constructors //
1541
//////////////////
1542
1543
template<value_t> struct external_constructor;
1544
1545
template<>
1546
struct external_constructor<value_t::boolean>
1547
{
1548
    template<typename BasicJsonType>
1549
    static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
1550
603
    {
1551
603
        j.m_type = value_t::boolean;
1552
603
        j.m_value = b;
1553
603
        j.assert_invariant();
1554
603
    }
1555
};
1556
1557
template<>
1558
struct external_constructor<value_t::string>
1559
{
1560
    template<typename BasicJsonType>
1561
    static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
1562
62.5k
    {
1563
62.5k
        j.m_type = value_t::string;
1564
62.5k
        j.m_value = s;
1565
62.5k
        j.assert_invariant();
1566
62.5k
    }
1567
1568
    template<typename BasicJsonType>
1569
    static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
1570
423
    {
1571
423
        j.m_type = value_t::string;
1572
423
        j.m_value = std::move(s);
1573
423
        j.assert_invariant();
1574
423
    }
1575
1576
    template<typename BasicJsonType, typename CompatibleStringType,
1577
             enable_if_t<not std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
1578
                         int> = 0>
1579
    static void construct(BasicJsonType& j, const CompatibleStringType& str)
1580
210
    {
1581
210
        j.m_type = value_t::string;
1582
210
        j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
1583
210
        j.assert_invariant();
1584
210
    }
_ZN8nlohmann6detail20external_constructorILNS0_7value_tE3EE9constructINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEA474_cLi0EEEvRT_RKT0_
Line
Count
Source
1580
199
    {
1581
199
        j.m_type = value_t::string;
1582
199
        j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
1583
199
        j.assert_invariant();
1584
199
    }
_ZN8nlohmann6detail20external_constructorILNS0_7value_tE3EE9constructINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEPKcLi0EEEvRT_RKT0_
Line
Count
Source
1580
10
    {
1581
10
        j.m_type = value_t::string;
1582
10
        j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
1583
10
        j.assert_invariant();
1584
10
    }
_ZN8nlohmann6detail20external_constructorILNS0_7value_tE3EE9constructINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEA6_cLi0EEEvRT_RKT0_
Line
Count
Source
1580
1
    {
1581
1
        j.m_type = value_t::string;
1582
1
        j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
1583
1
        j.assert_invariant();
1584
1
    }
1585
};
1586
1587
template<>
1588
struct external_constructor<value_t::number_float>
1589
{
1590
    template<typename BasicJsonType>
1591
    static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
1592
57.4k
    {
1593
57.4k
        j.m_type = value_t::number_float;
1594
57.4k
        j.m_value = val;
1595
57.4k
        j.assert_invariant();
1596
57.4k
    }
1597
};
1598
1599
template<>
1600
struct external_constructor<value_t::number_unsigned>
1601
{
1602
    template<typename BasicJsonType>
1603
    static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
1604
77.1k
    {
1605
77.1k
        j.m_type = value_t::number_unsigned;
1606
77.1k
        j.m_value = val;
1607
77.1k
        j.assert_invariant();
1608
77.1k
    }
1609
};
1610
1611
template<>
1612
struct external_constructor<value_t::number_integer>
1613
{
1614
    template<typename BasicJsonType>
1615
    static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
1616
9.18k
    {
1617
9.18k
        j.m_type = value_t::number_integer;
1618
9.18k
        j.m_value = val;
1619
9.18k
        j.assert_invariant();
1620
9.18k
    }
1621
};
1622
1623
template<>
1624
struct external_constructor<value_t::array>
1625
{
1626
    template<typename BasicJsonType>
1627
    static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
1628
    {
1629
        j.m_type = value_t::array;
1630
        j.m_value = arr;
1631
        j.assert_invariant();
1632
    }
1633
1634
    template<typename BasicJsonType>
1635
    static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
1636
    {
1637
        j.m_type = value_t::array;
1638
        j.m_value = std::move(arr);
1639
        j.assert_invariant();
1640
    }
1641
1642
    template<typename BasicJsonType, typename CompatibleArrayType,
1643
             enable_if_t<not std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
1644
                         int> = 0>
1645
    static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
1646
    {
1647
        using std::begin;
1648
        using std::end;
1649
        j.m_type = value_t::array;
1650
        j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
1651
        j.assert_invariant();
1652
    }
1653
1654
    template<typename BasicJsonType>
1655
    static void construct(BasicJsonType& j, const std::vector<bool>& arr)
1656
    {
1657
        j.m_type = value_t::array;
1658
        j.m_value = value_t::array;
1659
        j.m_value.array->reserve(arr.size());
1660
        for (const bool x : arr)
1661
        {
1662
            j.m_value.array->push_back(x);
1663
        }
1664
        j.assert_invariant();
1665
    }
1666
1667
    template<typename BasicJsonType, typename T,
1668
             enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
1669
    static void construct(BasicJsonType& j, const std::valarray<T>& arr)
1670
    {
1671
        j.m_type = value_t::array;
1672
        j.m_value = value_t::array;
1673
        j.m_value.array->resize(arr.size());
1674
        std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin());
1675
        j.assert_invariant();
1676
    }
1677
};
1678
1679
template<>
1680
struct external_constructor<value_t::object>
1681
{
1682
    template<typename BasicJsonType>
1683
    static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
1684
    {
1685
        j.m_type = value_t::object;
1686
        j.m_value = obj;
1687
        j.assert_invariant();
1688
    }
1689
1690
    template<typename BasicJsonType>
1691
    static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
1692
    {
1693
        j.m_type = value_t::object;
1694
        j.m_value = std::move(obj);
1695
        j.assert_invariant();
1696
    }
1697
1698
    template<typename BasicJsonType, typename CompatibleObjectType,
1699
             enable_if_t<not std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int> = 0>
1700
    static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
1701
    {
1702
        using std::begin;
1703
        using std::end;
1704
1705
        j.m_type = value_t::object;
1706
        j.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
1707
        j.assert_invariant();
1708
    }
1709
};
1710
1711
/////////////
1712
// to_json //
1713
/////////////
1714
1715
template<typename BasicJsonType, typename T,
1716
         enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
1717
void to_json(BasicJsonType& j, T b) noexcept
1718
603
{
1719
603
    external_constructor<value_t::boolean>::construct(j, b);
1720
603
}
1721
1722
template<typename BasicJsonType, typename CompatibleString,
1723
         enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
1724
void to_json(BasicJsonType& j, const CompatibleString& s)
1725
62.7k
{
1726
62.7k
    external_constructor<value_t::string>::construct(j, s);
1727
62.7k
}
_ZN8nlohmann6detail7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEESA_Li0EEEvRT_RKT0_
Line
Count
Source
1725
62.5k
{
1726
62.5k
    external_constructor<value_t::string>::construct(j, s);
1727
62.5k
}
_ZN8nlohmann6detail7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEA474_cLi0EEEvRT_RKT0_
Line
Count
Source
1725
199
{
1726
199
    external_constructor<value_t::string>::construct(j, s);
1727
199
}
_ZN8nlohmann6detail7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEPKcLi0EEEvRT_RKT0_
Line
Count
Source
1725
10
{
1726
10
    external_constructor<value_t::string>::construct(j, s);
1727
10
}
_ZN8nlohmann6detail7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEA6_cLi0EEEvRT_RKT0_
Line
Count
Source
1725
1
{
1726
1
    external_constructor<value_t::string>::construct(j, s);
1727
1
}
1728
1729
template<typename BasicJsonType>
1730
void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
1731
423
{
1732
423
    external_constructor<value_t::string>::construct(j, std::move(s));
1733
423
}
1734
1735
template<typename BasicJsonType, typename FloatType,
1736
         enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
1737
void to_json(BasicJsonType& j, FloatType val) noexcept
1738
57.4k
{
1739
57.4k
    external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
1740
57.4k
}
1741
1742
template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
1743
         enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
1744
void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
1745
77.1k
{
1746
77.1k
    external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
1747
77.1k
}
_ZN8nlohmann6detail7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEmLi0EEEvRT_T0_
Line
Count
Source
1745
77.0k
{
1746
77.0k
    external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
1747
77.0k
}
_ZN8nlohmann6detail7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEjLi0EEEvRT_T0_
Line
Count
Source
1745
141
{
1746
141
    external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
1747
141
}
1748
1749
template<typename BasicJsonType, typename CompatibleNumberIntegerType,
1750
         enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
1751
void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
1752
9.18k
{
1753
9.18k
    external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
1754
9.18k
}
_ZN8nlohmann6detail7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEElLi0EEEvRT_T0_
Line
Count
Source
1752
9.18k
{
1753
9.18k
    external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
1754
9.18k
}
_ZN8nlohmann6detail7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEiLi0EEEvRT_T0_
Line
Count
Source
1752
1
{
1753
1
    external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
1754
1
}
1755
1756
template<typename BasicJsonType, typename EnumType,
1757
         enable_if_t<std::is_enum<EnumType>::value, int> = 0>
1758
void to_json(BasicJsonType& j, EnumType e) noexcept
1759
{
1760
    using underlying_type = typename std::underlying_type<EnumType>::type;
1761
    external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
1762
}
1763
1764
template<typename BasicJsonType>
1765
void to_json(BasicJsonType& j, const std::vector<bool>& e)
1766
{
1767
    external_constructor<value_t::array>::construct(j, e);
1768
}
1769
1770
template <typename BasicJsonType, typename CompatibleArrayType,
1771
          enable_if_t<is_compatible_array_type<BasicJsonType,
1772
                      CompatibleArrayType>::value and
1773
                      not is_compatible_object_type<
1774
                          BasicJsonType, CompatibleArrayType>::value and
1775
                      not is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value and
1776
                      not is_basic_json<CompatibleArrayType>::value,
1777
                      int> = 0>
1778
void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
1779
{
1780
    external_constructor<value_t::array>::construct(j, arr);
1781
}
1782
1783
template<typename BasicJsonType, typename T,
1784
         enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
1785
void to_json(BasicJsonType& j, const std::valarray<T>& arr)
1786
{
1787
    external_constructor<value_t::array>::construct(j, std::move(arr));
1788
}
1789
1790
template<typename BasicJsonType>
1791
void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
1792
{
1793
    external_constructor<value_t::array>::construct(j, std::move(arr));
1794
}
1795
1796
template<typename BasicJsonType, typename CompatibleObjectType,
1797
         enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value and not is_basic_json<CompatibleObjectType>::value, int> = 0>
1798
void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
1799
{
1800
    external_constructor<value_t::object>::construct(j, obj);
1801
}
1802
1803
template<typename BasicJsonType>
1804
void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
1805
{
1806
    external_constructor<value_t::object>::construct(j, std::move(obj));
1807
}
1808
1809
template <
1810
    typename BasicJsonType, typename T, std::size_t N,
1811
    enable_if_t<not std::is_constructible<typename BasicJsonType::string_t,
1812
                const T (&)[N]>::value,
1813
                int> = 0 >
1814
void to_json(BasicJsonType& j, const T (&arr)[N])
1815
{
1816
    external_constructor<value_t::array>::construct(j, arr);
1817
}
1818
1819
template<typename BasicJsonType, typename... Args>
1820
void to_json(BasicJsonType& j, const std::pair<Args...>& p)
1821
{
1822
    j = {p.first, p.second};
1823
}
1824
1825
// for https://github.com/nlohmann/json/pull/1134
1826
template<typename BasicJsonType, typename T,
1827
         enable_if_t<std::is_same<T, typename iteration_proxy<typename BasicJsonType::iterator>::iteration_proxy_internal>::value, int> = 0>
1828
void to_json(BasicJsonType& j, T b) noexcept
1829
{
1830
    j = {{b.key(), b.value()}};
1831
}
1832
1833
template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
1834
void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...>)
1835
{
1836
    j = {std::get<Idx>(t)...};
1837
}
1838
1839
template<typename BasicJsonType, typename... Args>
1840
void to_json(BasicJsonType& j, const std::tuple<Args...>& t)
1841
{
1842
    to_json_tuple_impl(j, t, index_sequence_for<Args...> {});
1843
}
1844
1845
struct to_json_fn
1846
{
1847
    template<typename BasicJsonType, typename T>
1848
    auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
1849
    -> decltype(to_json(j, std::forward<T>(val)), void())
1850
207k
    {
1851
207k
        return to_json(j, std::forward<T>(val));
1852
207k
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEERSB_EEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
Line
Count
Source
1850
62.5k
    {
1851
62.5k
        return to_json(j, std::forward<T>(val));
1852
62.5k
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEERdEEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
Line
Count
Source
1850
57.4k
    {
1851
57.4k
        return to_json(j, std::forward<T>(val));
1852
57.4k
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEERbEEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
Line
Count
Source
1850
602
    {
1851
602
        return to_json(j, std::forward<T>(val));
1852
602
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEERlEEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
Line
Count
Source
1850
9.18k
    {
1851
9.18k
        return to_json(j, std::forward<T>(val));
1852
9.18k
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEERmEEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
Line
Count
Source
1850
77.0k
    {
1851
77.0k
        return to_json(j, std::forward<T>(val));
1852
77.0k
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEERA474_KcEEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSH_
Line
Count
Source
1850
199
    {
1851
199
        return to_json(j, std::forward<T>(val));
1852
199
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEESB_EEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSE_
Line
Count
Source
1850
423
    {
1851
423
        return to_json(j, std::forward<T>(val));
1852
423
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEKSB_EEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
Line
Count
Source
1850
47
    {
1851
47
        return to_json(j, std::forward<T>(val));
1852
47
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEERjEEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
Line
Count
Source
1850
141
    {
1851
141
        return to_json(j, std::forward<T>(val));
1852
141
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEERKPKcEEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSI_
Line
Count
Source
1850
10
    {
1851
10
        return to_json(j, std::forward<T>(val));
1852
10
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEbEEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSE_
Line
Count
Source
1850
1
    {
1851
1
        return to_json(j, std::forward<T>(val));
1852
1
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEdEEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSE_
Line
Count
Source
1850
1
    {
1851
1
        return to_json(j, std::forward<T>(val));
1852
1
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEERA6_KcEEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSH_
Line
Count
Source
1850
1
    {
1851
1
        return to_json(j, std::forward<T>(val));
1852
1
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEiEEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSE_
Line
Count
Source
1850
1
    {
1851
1
        return to_json(j, std::forward<T>(val));
1852
1
    }
1853
};
1854
}
1855
1856
/// namespace to hold default `to_json` function
1857
namespace
1858
{
1859
constexpr const auto& to_json = detail::static_const<detail::to_json_fn>::value;
1860
}
1861
}
1862
1863
// #include <nlohmann/detail/input/input_adapters.hpp>
1864
1865
1866
#include <cassert> // assert
1867
#include <cstddef> // size_t
1868
#include <cstring> // strlen
1869
#include <istream> // istream
1870
#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
1871
#include <memory> // shared_ptr, make_shared, addressof
1872
#include <numeric> // accumulate
1873
#include <string> // string, char_traits
1874
#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
1875
#include <utility> // pair, declval
1876
1877
// #include <nlohmann/detail/macro_scope.hpp>
1878
1879
1880
namespace nlohmann
1881
{
1882
namespace detail
1883
{
1884
/// the supported input formats
1885
enum class input_format_t { json, cbor, msgpack, ubjson };
1886
1887
////////////////////
1888
// input adapters //
1889
////////////////////
1890
1891
/*!
1892
@brief abstract input adapter interface
1893
1894
Produces a stream of std::char_traits<char>::int_type characters from a
1895
std::istream, a buffer, or some other input type. Accepts the return of
1896
exactly one non-EOF character for future input. The int_type characters
1897
returned consist of all valid char values as positive values (typically
1898
unsigned char), plus an EOF value outside that range, specified by the value
1899
of the function std::char_traits<char>::eof(). This value is typically -1, but
1900
could be any arbitrary value which is not a valid char value.
1901
*/
1902
struct input_adapter_protocol
1903
{
1904
    /// get a character [0,255] or std::char_traits<char>::eof().
1905
    virtual std::char_traits<char>::int_type get_character() = 0;
1906
835
    virtual ~input_adapter_protocol() = default;
1907
};
1908
1909
/// a type to simplify interfaces
1910
using input_adapter_t = std::shared_ptr<input_adapter_protocol>;
1911
1912
/*!
1913
Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at
1914
beginning of input. Does not support changing the underlying std::streambuf
1915
in mid-input. Maintains underlying std::istream and std::streambuf to support
1916
subsequent use of standard std::istream operations to process any input
1917
characters following those used in parsing the JSON input.  Clears the
1918
std::istream flags; any input errors (e.g., EOF) will be detected by the first
1919
subsequent call for input from the std::istream.
1920
*/
1921
class input_stream_adapter : public input_adapter_protocol
1922
{
1923
  public:
1924
    ~input_stream_adapter() override
1925
198
    {
1926
198
        // clear stream flags; we use underlying streambuf I/O, do not
1927
198
        // maintain ifstream flags
1928
198
        is.clear();
1929
198
    }
1930
1931
    explicit input_stream_adapter(std::istream& i)
1932
        : is(i), sb(*i.rdbuf())
1933
198
    {}
1934
1935
    // delete because of pointer members
1936
    input_stream_adapter(const input_stream_adapter&) = delete;
1937
    input_stream_adapter& operator=(input_stream_adapter&) = delete;
1938
1939
    // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
1940
    // ensure that std::char_traits<char>::eof() and the character 0xFF do not
1941
    // end up as the same value, eg. 0xFFFFFFFF.
1942
    std::char_traits<char>::int_type get_character() override
1943
451k
    {
1944
451k
        return sb.sbumpc();
1945
451k
    }
1946
1947
  private:
1948
    /// the associated input stream
1949
    std::istream& is;
1950
    std::streambuf& sb;
1951
};
1952
1953
/// input adapter for buffer input
1954
class input_buffer_adapter : public input_adapter_protocol
1955
{
1956
  public:
1957
    input_buffer_adapter(const char* b, const std::size_t l)
1958
        : cursor(b), limit(b + l)
1959
637
    {}
1960
1961
    // delete because of pointer members
1962
    input_buffer_adapter(const input_buffer_adapter&) = delete;
1963
    input_buffer_adapter& operator=(input_buffer_adapter&) = delete;
1964
1965
    std::char_traits<char>::int_type get_character() noexcept override
1966
4.12M
    {
1967
4.12M
        if (JSON_LIKELY(cursor < limit))
1968
4.12M
        {
1969
4.12M
            return std::char_traits<char>::to_int_type(*(cursor++));
1970
4.12M
        }
1971
40
1972
40
        return std::char_traits<char>::eof();
1973
40
    }
1974
1975
  private:
1976
    /// pointer to the current character
1977
    const char* cursor;
1978
    /// pointer past the last character
1979
    const char* const limit;
1980
};
1981
1982
template<typename WideStringType>
1983
class wide_string_input_adapter : public input_adapter_protocol
1984
{
1985
  public:
1986
    explicit wide_string_input_adapter(const WideStringType& w) : str(w) {}
1987
1988
    std::char_traits<char>::int_type get_character() noexcept override
1989
0
    {
1990
0
        // check if buffer needs to be filled
1991
0
        if (utf8_bytes_index == utf8_bytes_filled)
1992
0
        {
1993
0
            if (sizeof(typename WideStringType::value_type) == 2)
1994
0
            {
1995
0
                fill_buffer_utf16();
1996
0
            }
1997
0
            else
1998
0
            {
1999
0
                fill_buffer_utf32();
2000
0
            }
2001
0
2002
0
            assert(utf8_bytes_filled > 0);
2003
0
            assert(utf8_bytes_index == 0);
2004
0
        }
2005
0
2006
0
        // use buffer
2007
0
        assert(utf8_bytes_filled > 0);
2008
0
        assert(utf8_bytes_index < utf8_bytes_filled);
2009
0
        return utf8_bytes[utf8_bytes_index++];
2010
0
    }
Unexecuted instantiation: _ZN8nlohmann6detail25wide_string_input_adapterINSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEEEE13get_characterEv
Unexecuted instantiation: _ZN8nlohmann6detail25wide_string_input_adapterINSt7__cxx1112basic_stringIDsSt11char_traitsIDsESaIDsEEEE13get_characterEv
Unexecuted instantiation: _ZN8nlohmann6detail25wide_string_input_adapterINSt7__cxx1112basic_stringIDiSt11char_traitsIDiESaIDiEEEE13get_characterEv
2011
2012
  private:
2013
    void fill_buffer_utf16()
2014
0
    {
2015
0
        utf8_bytes_index = 0;
2016
0
2017
0
        if (current_wchar == str.size())
2018
0
        {
2019
0
            utf8_bytes[0] = std::char_traits<char>::eof();
2020
0
            utf8_bytes_filled = 1;
2021
0
        }
2022
0
        else
2023
0
        {
2024
0
            // get the current character
2025
0
            const int wc = static_cast<int>(str[current_wchar++]);
2026
0
2027
0
            // UTF-16 to UTF-8 encoding
2028
0
            if (wc < 0x80)
2029
0
            {
2030
0
                utf8_bytes[0] = wc;
2031
0
                utf8_bytes_filled = 1;
2032
0
            }
2033
0
            else if (wc <= 0x7FF)
2034
0
            {
2035
0
                utf8_bytes[0] = 0xC0 | ((wc >> 6));
2036
0
                utf8_bytes[1] = 0x80 | (wc & 0x3F);
2037
0
                utf8_bytes_filled = 2;
2038
0
            }
2039
0
            else if (0xD800 > wc or wc >= 0xE000)
2040
0
            {
2041
0
                utf8_bytes[0] = 0xE0 | ((wc >> 12));
2042
0
                utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F);
2043
0
                utf8_bytes[2] = 0x80 | (wc & 0x3F);
2044
0
                utf8_bytes_filled = 3;
2045
0
            }
2046
0
            else
2047
0
            {
2048
0
                if (current_wchar < str.size())
2049
0
                {
2050
0
                    const int wc2 = static_cast<int>(str[current_wchar++]);
2051
0
                    const int charcode = 0x10000 + (((wc & 0x3FF) << 10) | (wc2 & 0x3FF));
2052
0
                    utf8_bytes[0] = 0xf0 | (charcode >> 18);
2053
0
                    utf8_bytes[1] = 0x80 | ((charcode >> 12) & 0x3F);
2054
0
                    utf8_bytes[2] = 0x80 | ((charcode >> 6) & 0x3F);
2055
0
                    utf8_bytes[3] = 0x80 | (charcode & 0x3F);
2056
0
                    utf8_bytes_filled = 4;
2057
0
                }
2058
0
                else
2059
0
                {
2060
0
                    // unknown character
2061
0
                    ++current_wchar;
2062
0
                    utf8_bytes[0] = wc;
2063
0
                    utf8_bytes_filled = 1;
2064
0
                }
2065
0
            }
2066
0
        }
2067
0
    }
Unexecuted instantiation: _ZN8nlohmann6detail25wide_string_input_adapterINSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEEEE17fill_buffer_utf16Ev
Unexecuted instantiation: _ZN8nlohmann6detail25wide_string_input_adapterINSt7__cxx1112basic_stringIDsSt11char_traitsIDsESaIDsEEEE17fill_buffer_utf16Ev
Unexecuted instantiation: _ZN8nlohmann6detail25wide_string_input_adapterINSt7__cxx1112basic_stringIDiSt11char_traitsIDiESaIDiEEEE17fill_buffer_utf16Ev
2068
2069
    void fill_buffer_utf32()
2070
0
    {
2071
0
        utf8_bytes_index = 0;
2072
0
2073
0
        if (current_wchar == str.size())
2074
0
        {
2075
0
            utf8_bytes[0] = std::char_traits<char>::eof();
2076
0
            utf8_bytes_filled = 1;
2077
0
        }
2078
0
        else
2079
0
        {
2080
0
            // get the current character
2081
0
            const int wc = static_cast<int>(str[current_wchar++]);
2082
0
2083
0
            // UTF-32 to UTF-8 encoding
2084
0
            if (wc < 0x80)
2085
0
            {
2086
0
                utf8_bytes[0] = wc;
2087
0
                utf8_bytes_filled = 1;
2088
0
            }
2089
0
            else if (wc <= 0x7FF)
2090
0
            {
2091
0
                utf8_bytes[0] = 0xC0 | ((wc >> 6) & 0x1F);
2092
0
                utf8_bytes[1] = 0x80 | (wc & 0x3F);
2093
0
                utf8_bytes_filled = 2;
2094
0
            }
2095
0
            else if (wc <= 0xFFFF)
2096
0
            {
2097
0
                utf8_bytes[0] = 0xE0 | ((wc >> 12) & 0x0F);
2098
0
                utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F);
2099
0
                utf8_bytes[2] = 0x80 | (wc & 0x3F);
2100
0
                utf8_bytes_filled = 3;
2101
0
            }
2102
0
            else if (wc <= 0x10FFFF)
2103
0
            {
2104
0
                utf8_bytes[0] = 0xF0 | ((wc >> 18 ) & 0x07);
2105
0
                utf8_bytes[1] = 0x80 | ((wc >> 12) & 0x3F);
2106
0
                utf8_bytes[2] = 0x80 | ((wc >> 6) & 0x3F);
2107
0
                utf8_bytes[3] = 0x80 | (wc & 0x3F);
2108
0
                utf8_bytes_filled = 4;
2109
0
            }
2110
0
            else
2111
0
            {
2112
0
                // unknown character
2113
0
                utf8_bytes[0] = wc;
2114
0
                utf8_bytes_filled = 1;
2115
0
            }
2116
0
        }
2117
0
    }
Unexecuted instantiation: _ZN8nlohmann6detail25wide_string_input_adapterINSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEEEE17fill_buffer_utf32Ev
Unexecuted instantiation: _ZN8nlohmann6detail25wide_string_input_adapterINSt7__cxx1112basic_stringIDsSt11char_traitsIDsESaIDsEEEE17fill_buffer_utf32Ev
Unexecuted instantiation: _ZN8nlohmann6detail25wide_string_input_adapterINSt7__cxx1112basic_stringIDiSt11char_traitsIDiESaIDiEEEE17fill_buffer_utf32Ev
2118
2119
  private:
2120
    /// the wstring to process
2121
    const WideStringType& str;
2122
2123
    /// index of the current wchar in str
2124
    std::size_t current_wchar = 0;
2125
2126
    /// a buffer for UTF-8 bytes
2127
    std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
2128
2129
    /// index to the utf8_codes array for the next valid byte
2130
    std::size_t utf8_bytes_index = 0;
2131
    /// number of valid bytes in the utf8_codes array
2132
    std::size_t utf8_bytes_filled = 0;
2133
};
2134
2135
class input_adapter
2136
{
2137
  public:
2138
    // native support
2139
2140
    /// input adapter for input stream
2141
    input_adapter(std::istream& i)
2142
198
        : ia(std::make_shared<input_stream_adapter>(i)) {}
2143
2144
    /// input adapter for input stream
2145
    input_adapter(std::istream&& i)
2146
0
        : ia(std::make_shared<input_stream_adapter>(i)) {}
2147
2148
    input_adapter(const std::wstring& ws)
2149
0
        : ia(std::make_shared<wide_string_input_adapter<std::wstring>>(ws)) {}
2150
2151
    input_adapter(const std::u16string& ws)
2152
0
        : ia(std::make_shared<wide_string_input_adapter<std::u16string>>(ws)) {}
2153
2154
    input_adapter(const std::u32string& ws)
2155
0
        : ia(std::make_shared<wide_string_input_adapter<std::u32string>>(ws)) {}
2156
2157
    /// input adapter for buffer
2158
    template<typename CharT,
2159
             typename std::enable_if<
2160
                 std::is_pointer<CharT>::value and
2161
                 std::is_integral<typename std::remove_pointer<CharT>::type>::value and
2162
                 sizeof(typename std::remove_pointer<CharT>::type) == 1,
2163
                 int>::type = 0>
2164
    input_adapter(CharT b, std::size_t l)
2165
        : ia(std::make_shared<input_buffer_adapter>(reinterpret_cast<const char*>(b), l)) {}
2166
2167
    // derived support
2168
2169
    /// input adapter for string literal
2170
    template<typename CharT,
2171
             typename std::enable_if<
2172
                 std::is_pointer<CharT>::value and
2173
                 std::is_integral<typename std::remove_pointer<CharT>::type>::value and
2174
                 sizeof(typename std::remove_pointer<CharT>::type) == 1,
2175
                 int>::type = 0>
2176
    input_adapter(CharT b)
2177
        : input_adapter(reinterpret_cast<const char*>(b),
2178
                        std::strlen(reinterpret_cast<const char*>(b))) {}
2179
2180
    /// input adapter for iterator range with contiguous storage
2181
    template<class IteratorType,
2182
             typename std::enable_if<
2183
                 std::is_same<typename std::iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
2184
                 int>::type = 0>
2185
    input_adapter(IteratorType first, IteratorType last)
2186
637
    {
2187
637
#ifndef NDEBUG
2188
637
        // assertion to check that the iterator range is indeed contiguous,
2189
637
        // see http://stackoverflow.com/a/35008842/266378 for more discussion
2190
637
        const auto is_contiguous = std::accumulate(
2191
637
                                       first, last, std::pair<bool, int>(true, 0),
2192
637
                                       [&first](std::pair<bool, int> res, decltype(*first) val)
2193
4.12M
        {
2194
4.12M
            res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
2195
4.12M
            return res;
2196
4.12M
        }).first;
_ZZN8nlohmann6detail13input_adapterC1IN9__gnu_cxx17__normal_iteratorIPKcNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEELi0EEET_SE_ENKUlSt4pairIbiERS5_E_clESG_SH_
Line
Count
Source
2193
12.5k
        {
2194
12.5k
            res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
2195
12.5k
            return res;
2196
12.5k
        }).first;
_ZZN8nlohmann6detail13input_adapterC1IPKcLi0EEET_S5_ENKUlSt4pairIbiERS3_E_clES7_S8_
Line
Count
Source
2193
4.11M
        {
2194
4.11M
            res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
2195
4.11M
            return res;
2196
4.11M
        }).first;
2197
637
        assert(is_contiguous);
2198
637
#endif
2199
637
2200
637
        // assertion to check that each element is 1 byte long
2201
637
        static_assert(
2202
637
            sizeof(typename std::iterator_traits<IteratorType>::value_type) == 1,
2203
637
            "each element in the iterator range must have the size of 1 byte");
2204
637
2205
637
        const auto len = static_cast<size_t>(std::distance(first, last));
2206
637
        if (JSON_LIKELY(len > 0))
2207
637
        {
2208
637
            // there is at least one element: use the address of first
2209
637
            ia = std::make_shared<input_buffer_adapter>(reinterpret_cast<const char*>(&(*first)), len);
2210
637
        }
2211
0
        else
2212
0
        {
2213
0
            // the address of first cannot be used: use nullptr
2214
0
            ia = std::make_shared<input_buffer_adapter>(nullptr, len);
2215
0
        }
2216
637
    }
_ZN8nlohmann6detail13input_adapterC2IN9__gnu_cxx17__normal_iteratorIPKcNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEELi0EEET_SE_
Line
Count
Source
2186
40
    {
2187
40
#ifndef NDEBUG
2188
40
        // assertion to check that the iterator range is indeed contiguous,
2189
40
        // see http://stackoverflow.com/a/35008842/266378 for more discussion
2190
40
        const auto is_contiguous = std::accumulate(
2191
40
                                       first, last, std::pair<bool, int>(true, 0),
2192
40
                                       [&first](std::pair<bool, int> res, decltype(*first) val)
2193
40
        {
2194
40
            res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
2195
40
            return res;
2196
40
        }).first;
2197
40
        assert(is_contiguous);
2198
40
#endif
2199
40
2200
40
        // assertion to check that each element is 1 byte long
2201
40
        static_assert(
2202
40
            sizeof(typename std::iterator_traits<IteratorType>::value_type) == 1,
2203
40
            "each element in the iterator range must have the size of 1 byte");
2204
40
2205
40
        const auto len = static_cast<size_t>(std::distance(first, last));
2206
40
        if (JSON_LIKELY(len > 0))
2207
40
        {
2208
40
            // there is at least one element: use the address of first
2209
40
            ia = std::make_shared<input_buffer_adapter>(reinterpret_cast<const char*>(&(*first)), len);
2210
40
        }
2211
0
        else
2212
0
        {
2213
0
            // the address of first cannot be used: use nullptr
2214
0
            ia = std::make_shared<input_buffer_adapter>(nullptr, len);
2215
0
        }
2216
40
    }
_ZN8nlohmann6detail13input_adapterC2IPKcLi0EEET_S5_
Line
Count
Source
2186
597
    {
2187
597
#ifndef NDEBUG
2188
597
        // assertion to check that the iterator range is indeed contiguous,
2189
597
        // see http://stackoverflow.com/a/35008842/266378 for more discussion
2190
597
        const auto is_contiguous = std::accumulate(
2191
597
                                       first, last, std::pair<bool, int>(true, 0),
2192
597
                                       [&first](std::pair<bool, int> res, decltype(*first) val)
2193
597
        {
2194
597
            res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
2195
597
            return res;
2196
597
        }).first;
2197
597
        assert(is_contiguous);
2198
597
#endif
2199
597
2200
597
        // assertion to check that each element is 1 byte long
2201
597
        static_assert(
2202
597
            sizeof(typename std::iterator_traits<IteratorType>::value_type) == 1,
2203
597
            "each element in the iterator range must have the size of 1 byte");
2204
597
2205
597
        const auto len = static_cast<size_t>(std::distance(first, last));
2206
597
        if (JSON_LIKELY(len > 0))
2207
597
        {
2208
597
            // there is at least one element: use the address of first
2209
597
            ia = std::make_shared<input_buffer_adapter>(reinterpret_cast<const char*>(&(*first)), len);
2210
597
        }
2211
0
        else
2212
0
        {
2213
0
            // the address of first cannot be used: use nullptr
2214
0
            ia = std::make_shared<input_buffer_adapter>(nullptr, len);
2215
0
        }
2216
597
    }
2217
2218
    /// input adapter for array
2219
    template<class T, std::size_t N>
2220
    input_adapter(T (&array)[N])
2221
597
        : input_adapter(std::begin(array), std::end(array)) {}
_ZN8nlohmann6detail13input_adapterC2IKcLm117EEERAT0__T_
Line
Count
Source
2221
199
        : input_adapter(std::begin(array), std::end(array)) {}
_ZN8nlohmann6detail13input_adapterC2IKcLm10282EEERAT0__T_
Line
Count
Source
2221
199
        : input_adapter(std::begin(array), std::end(array)) {}
_ZN8nlohmann6detail13input_adapterC2IKcLm10259EEERAT0__T_
Line
Count
Source
2221
199
        : input_adapter(std::begin(array), std::end(array)) {}
2222
2223
    /// input adapter for contiguous container
2224
    template<class ContiguousContainer, typename
2225
             std::enable_if<not std::is_pointer<ContiguousContainer>::value and
2226
                            std::is_base_of<std::random_access_iterator_tag, typename std::iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value,
2227
                            int>::type = 0>
2228
    input_adapter(const ContiguousContainer& c)
2229
40
        : input_adapter(std::begin(c), std::end(c)) {}
2230
2231
    operator input_adapter_t()
2232
835
    {
2233
835
        return ia;
2234
835
    }
2235
2236
  private:
2237
    /// the actual adapter
2238
    input_adapter_t ia = nullptr;
2239
};
2240
}
2241
}
2242
2243
// #include <nlohmann/detail/input/lexer.hpp>
2244
2245
2246
#include <clocale> // localeconv
2247
#include <cstddef> // size_t
2248
#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
2249
#include <cstdio> // snprintf
2250
#include <initializer_list> // initializer_list
2251
#include <string> // char_traits, string
2252
#include <vector> // vector
2253
2254
// #include <nlohmann/detail/macro_scope.hpp>
2255
2256
// #include <nlohmann/detail/input/input_adapters.hpp>
2257
2258
2259
namespace nlohmann
2260
{
2261
namespace detail
2262
{
2263
///////////
2264
// lexer //
2265
///////////
2266
2267
/*!
2268
@brief lexical analysis
2269
2270
This class organizes the lexical analysis during JSON deserialization.
2271
*/
2272
template<typename BasicJsonType>
2273
class lexer
2274
{
2275
    using number_integer_t = typename BasicJsonType::number_integer_t;
2276
    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
2277
    using number_float_t = typename BasicJsonType::number_float_t;
2278
    using string_t = typename BasicJsonType::string_t;
2279
2280
  public:
2281
    /// token types for the parser
2282
    enum class token_type
2283
    {
2284
        uninitialized,    ///< indicating the scanner is uninitialized
2285
        literal_true,     ///< the `true` literal
2286
        literal_false,    ///< the `false` literal
2287
        literal_null,     ///< the `null` literal
2288
        value_string,     ///< a string -- use get_string() for actual value
2289
        value_unsigned,   ///< an unsigned integer -- use get_number_unsigned() for actual value
2290
        value_integer,    ///< a signed integer -- use get_number_integer() for actual value
2291
        value_float,      ///< an floating point number -- use get_number_float() for actual value
2292
        begin_array,      ///< the character for array begin `[`
2293
        begin_object,     ///< the character for object begin `{`
2294
        end_array,        ///< the character for array end `]`
2295
        end_object,       ///< the character for object end `}`
2296
        name_separator,   ///< the name separator `:`
2297
        value_separator,  ///< the value separator `,`
2298
        parse_error,      ///< indicating a parse error
2299
        end_of_input,     ///< indicating the end of the input buffer
2300
        literal_or_value  ///< a literal or the begin of a value (only for diagnostics)
2301
    };
2302
2303
    /// return name of values of type token_type (only used for errors)
2304
    static const char* token_type_name(const token_type t) noexcept
2305
2
    {
2306
2
        switch (t)
2307
2
        {
2308
2
            case token_type::uninitialized:
2309
0
                return "<uninitialized>";
2310
2
            case token_type::literal_true:
2311
0
                return "true literal";
2312
2
            case token_type::literal_false:
2313
0
                return "false literal";
2314
2
            case token_type::literal_null:
2315
0
                return "null literal";
2316
2
            case token_type::value_string:
2317
0
                return "string literal";
2318
2
            case lexer::token_type::value_unsigned:
2319
0
            case lexer::token_type::value_integer:
2320
0
            case lexer::token_type::value_float:
2321
0
                return "number literal";
2322
0
            case token_type::begin_array:
2323
0
                return "'['";
2324
0
            case token_type::begin_object:
2325
0
                return "'{'";
2326
0
            case token_type::end_array:
2327
0
                return "']'";
2328
0
            case token_type::end_object:
2329
0
                return "'}'";
2330
0
            case token_type::name_separator:
2331
0
                return "':'";
2332
0
            case token_type::value_separator:
2333
0
                return "','";
2334
0
            case token_type::parse_error:
2335
0
                return "<parse error>";
2336
1
            case token_type::end_of_input:
2337
1
                return "end of input";
2338
1
            case token_type::literal_or_value:
2339
1
                return "'[', '{', or a literal";
2340
0
            // LCOV_EXCL_START
2341
0
            default: // catch non-enum values
2342
0
                return "unknown token";
2343
0
                // LCOV_EXCL_STOP
2344
0
        }
2345
0
    }
2346
2347
    explicit lexer(detail::input_adapter_t&& adapter)
2348
835
        : ia(std::move(adapter)), decimal_point_char(get_decimal_point()) {}
2349
2350
    // delete because of pointer members
2351
    lexer(const lexer&) = delete;
2352
    lexer& operator=(lexer&) = delete;
2353
2354
  private:
2355
    /////////////////////
2356
    // locales
2357
    /////////////////////
2358
2359
    /// return the locale-dependent decimal point
2360
    static char get_decimal_point() noexcept
2361
835
    {
2362
835
        const auto loc = localeconv();
2363
835
        assert(loc != nullptr);
2364
835
        return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
2365
835
    }
2366
2367
    /////////////////////
2368
    // scan functions
2369
    /////////////////////
2370
2371
    /*!
2372
    @brief get codepoint from 4 hex characters following `\u`
2373
2374
    For input "\u c1 c2 c3 c4" the codepoint is:
2375
      (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4
2376
    = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0)
2377
2378
    Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f'
2379
    must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The
2380
    conversion is done by subtracting the offset (0x30, 0x37, and 0x57)
2381
    between the ASCII value of the character and the desired integer value.
2382
2383
    @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or
2384
            non-hex character)
2385
    */
2386
    int get_codepoint()
2387
0
    {
2388
0
        // this function only makes sense after reading `\u`
2389
0
        assert(current == 'u');
2390
0
        int codepoint = 0;
2391
0
2392
0
        const auto factors = { 12, 8, 4, 0 };
2393
0
        for (const auto factor : factors)
2394
0
        {
2395
0
            get();
2396
0
2397
0
            if (current >= '0' and current <= '9')
2398
0
            {
2399
0
                codepoint += ((current - 0x30) << factor);
2400
0
            }
2401
0
            else if (current >= 'A' and current <= 'F')
2402
0
            {
2403
0
                codepoint += ((current - 0x37) << factor);
2404
0
            }
2405
0
            else if (current >= 'a' and current <= 'f')
2406
0
            {
2407
0
                codepoint += ((current - 0x57) << factor);
2408
0
            }
2409
0
            else
2410
0
            {
2411
0
                return -1;
2412
0
            }
2413
0
        }
2414
0
2415
0
        assert(0x0000 <= codepoint and codepoint <= 0xFFFF);
2416
0
        return codepoint;
2417
0
    }
2418
2419
    /*!
2420
    @brief check if the next byte(s) are inside a given range
2421
2422
    Adds the current byte and, for each passed range, reads a new byte and
2423
    checks if it is inside the range. If a violation was detected, set up an
2424
    error message and return false. Otherwise, return true.
2425
2426
    @param[in] ranges  list of integers; interpreted as list of pairs of
2427
                       inclusive lower and upper bound, respectively
2428
2429
    @pre The passed list @a ranges must have 2, 4, or 6 elements; that is,
2430
         1, 2, or 3 pairs. This precondition is enforced by an assertion.
2431
2432
    @return true if and only if no range violation was detected
2433
    */
2434
    bool next_byte_in_range(std::initializer_list<int> ranges)
2435
0
    {
2436
0
        assert(ranges.size() == 2 or ranges.size() == 4 or ranges.size() == 6);
2437
0
        add(current);
2438
0
2439
0
        for (auto range = ranges.begin(); range != ranges.end(); ++range)
2440
0
        {
2441
0
            get();
2442
0
            if (JSON_LIKELY(*range <= current and current <= *(++range)))
2443
0
            {
2444
0
                add(current);
2445
0
            }
2446
0
            else
2447
0
            {
2448
0
                error_message = "invalid string: ill-formed UTF-8 byte";
2449
0
                return false;
2450
0
            }
2451
0
        }
2452
0
2453
0
        return true;
2454
0
    }
2455
2456
    /*!
2457
    @brief scan a string literal
2458
2459
    This function scans a string according to Sect. 7 of RFC 7159. While
2460
    scanning, bytes are escaped and copied into buffer token_buffer. Then the
2461
    function returns successfully, token_buffer is *not* null-terminated (as it
2462
    may contain \0 bytes), and token_buffer.size() is the number of bytes in the
2463
    string.
2464
2465
    @return token_type::value_string if string could be successfully scanned,
2466
            token_type::parse_error otherwise
2467
2468
    @note In case of errors, variable error_message contains a textual
2469
          description.
2470
    */
2471
    token_type scan_string()
2472
309k
    {
2473
309k
        // reset token_buffer (ignore opening quote)
2474
309k
        reset();
2475
309k
2476
309k
        // we entered the function by reading an open quote
2477
309k
        assert(current == '\"');
2478
309k
2479
2.74M
        while (true)
2480
2.74M
        {
2481
2.74M
            // get next character
2482
2.74M
            switch (get())
2483
2.74M
            {
2484
2.74M
                // end of file while parsing string
2485
2.74M
                case std::char_traits<char>::eof():
2486
0
                {
2487
0
                    error_message = "invalid string: missing closing quote";
2488
0
                    return token_type::parse_error;
2489
2.74M
                }
2490
2.74M
2491
2.74M
                // closing quote
2492
2.74M
                case '\"':
2493
309k
                {
2494
309k
                    return token_type::value_string;
2495
2.74M
                }
2496
2.74M
2497
2.74M
                // escapes
2498
2.74M
                case '\\':
2499
0
                {
2500
0
                    switch (get())
2501
0
                    {
2502
0
                        // quotation mark
2503
0
                        case '\"':
2504
0
                            add('\"');
2505
0
                            break;
2506
0
                        // reverse solidus
2507
0
                        case '\\':
2508
0
                            add('\\');
2509
0
                            break;
2510
0
                        // solidus
2511
0
                        case '/':
2512
0
                            add('/');
2513
0
                            break;
2514
0
                        // backspace
2515
0
                        case 'b':
2516
0
                            add('\b');
2517
0
                            break;
2518
0
                        // form feed
2519
0
                        case 'f':
2520
0
                            add('\f');
2521
0
                            break;
2522
0
                        // line feed
2523
0
                        case 'n':
2524
0
                            add('\n');
2525
0
                            break;
2526
0
                        // carriage return
2527
0
                        case 'r':
2528
0
                            add('\r');
2529
0
                            break;
2530
0
                        // tab
2531
0
                        case 't':
2532
0
                            add('\t');
2533
0
                            break;
2534
0
2535
0
                        // unicode escapes
2536
0
                        case 'u':
2537
0
                        {
2538
0
                            const int codepoint1 = get_codepoint();
2539
0
                            int codepoint = codepoint1; // start with codepoint1
2540
0
2541
0
                            if (JSON_UNLIKELY(codepoint1 == -1))
2542
0
                            {
2543
0
                                error_message = "invalid string: '\\u' must be followed by 4 hex digits";
2544
0
                                return token_type::parse_error;
2545
0
                            }
2546
0
2547
0
                            // check if code point is a high surrogate
2548
0
                            if (0xD800 <= codepoint1 and codepoint1 <= 0xDBFF)
2549
0
                            {
2550
0
                                // expect next \uxxxx entry
2551
0
                                if (JSON_LIKELY(get() == '\\' and get() == 'u'))
2552
0
                                {
2553
0
                                    const int codepoint2 = get_codepoint();
2554
0
2555
0
                                    if (JSON_UNLIKELY(codepoint2 == -1))
2556
0
                                    {
2557
0
                                        error_message = "invalid string: '\\u' must be followed by 4 hex digits";
2558
0
                                        return token_type::parse_error;
2559
0
                                    }
2560
0
2561
0
                                    // check if codepoint2 is a low surrogate
2562
0
                                    if (JSON_LIKELY(0xDC00 <= codepoint2 and codepoint2 <= 0xDFFF))
2563
0
                                    {
2564
0
                                        // overwrite codepoint
2565
0
                                        codepoint =
2566
0
                                            // high surrogate occupies the most significant 22 bits
2567
0
                                            (codepoint1 << 10)
2568
0
                                            // low surrogate occupies the least significant 15 bits
2569
0
                                            + codepoint2
2570
0
                                            // there is still the 0xD800, 0xDC00 and 0x10000 noise
2571
0
                                            // in the result so we have to subtract with:
2572
0
                                            // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
2573
0
                                            - 0x35FDC00;
2574
0
                                    }
2575
0
                                    else
2576
0
                                    {
2577
0
                                        error_message = "invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF";
2578
0
                                        return token_type::parse_error;
2579
0
                                    }
2580
0
                                }
2581
0
                                else
2582
0
                                {
2583
0
                                    error_message = "invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF";
2584
0
                                    return token_type::parse_error;
2585
0
                                }
2586
0
                            }
2587
0
                            else
2588
0
                            {
2589
0
                                if (JSON_UNLIKELY(0xDC00 <= codepoint1 and codepoint1 <= 0xDFFF))
2590
0
                                {
2591
0
                                    error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
2592
0
                                    return token_type::parse_error;
2593
0
                                }
2594
0
                            }
2595
0
2596
0
                            // result of the above calculation yields a proper codepoint
2597
0
                            assert(0x00 <= codepoint and codepoint <= 0x10FFFF);
2598
0
2599
0
                            // translate codepoint into bytes
2600
0
                            if (codepoint < 0x80)
2601
0
                            {
2602
0
                                // 1-byte characters: 0xxxxxxx (ASCII)
2603
0
                                add(codepoint);
2604
0
                            }
2605
0
                            else if (codepoint <= 0x7FF)
2606
0
                            {
2607
0
                                // 2-byte characters: 110xxxxx 10xxxxxx
2608
0
                                add(0xC0 | (codepoint >> 6));
2609
0
                                add(0x80 | (codepoint & 0x3F));
2610
0
                            }
2611
0
                            else if (codepoint <= 0xFFFF)
2612
0
                            {
2613
0
                                // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
2614
0
                                add(0xE0 | (codepoint >> 12));
2615
0
                                add(0x80 | ((codepoint >> 6) & 0x3F));
2616
0
                                add(0x80 | (codepoint & 0x3F));
2617
0
                            }
2618
0
                            else
2619
0
                            {
2620
0
                                // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
2621
0
                                add(0xF0 | (codepoint >> 18));
2622
0
                                add(0x80 | ((codepoint >> 12) & 0x3F));
2623
0
                                add(0x80 | ((codepoint >> 6) & 0x3F));
2624
0
                                add(0x80 | (codepoint & 0x3F));
2625
0
                            }
2626
0
2627
0
                            break;
2628
0
                        }
2629
0
2630
0
                        // other characters after escape
2631
0
                        default:
2632
0
                            error_message = "invalid string: forbidden character after backslash";
2633
0
                            return token_type::parse_error;
2634
0
                    }
2635
0
2636
0
                    break;
2637
0
                }
2638
0
2639
0
                // invalid control characters
2640
0
                case 0x00:
2641
0
                case 0x01:
2642
0
                case 0x02:
2643
0
                case 0x03:
2644
0
                case 0x04:
2645
0
                case 0x05:
2646
0
                case 0x06:
2647
0
                case 0x07:
2648
0
                case 0x08:
2649
0
                case 0x09:
2650
0
                case 0x0A:
2651
0
                case 0x0B:
2652
0
                case 0x0C:
2653
0
                case 0x0D:
2654
0
                case 0x0E:
2655
0
                case 0x0F:
2656
0
                case 0x10:
2657
0
                case 0x11:
2658
0
                case 0x12:
2659
0
                case 0x13:
2660
0
                case 0x14:
2661
0
                case 0x15:
2662
0
                case 0x16:
2663
0
                case 0x17:
2664
0
                case 0x18:
2665
0
                case 0x19:
2666
0
                case 0x1A:
2667
0
                case 0x1B:
2668
0
                case 0x1C:
2669
0
                case 0x1D:
2670
0
                case 0x1E:
2671
0
                case 0x1F:
2672
0
                {
2673
0
                    error_message = "invalid string: control character must be escaped";
2674
0
                    return token_type::parse_error;
2675
0
                }
2676
0
2677
0
                // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
2678
2.43M
                case 0x20:
2679
2.43M
                case 0x21:
2680
2.43M
                case 0x23:
2681
2.43M
                case 0x24:
2682
2.43M
                case 0x25:
2683
2.43M
                case 0x26:
2684
2.43M
                case 0x27:
2685
2.43M
                case 0x28:
2686
2.43M
                case 0x29:
2687
2.43M
                case 0x2A:
2688
2.43M
                case 0x2B:
2689
2.43M
                case 0x2C:
2690
2.43M
                case 0x2D:
2691
2.43M
                case 0x2E:
2692
2.43M
                case 0x2F:
2693
2.43M
                case 0x30:
2694
2.43M
                case 0x31:
2695
2.43M
                case 0x32:
2696
2.43M
                case 0x33:
2697
2.43M
                case 0x34:
2698
2.43M
                case 0x35:
2699
2.43M
                case 0x36:
2700
2.43M
                case 0x37:
2701
2.43M
                case 0x38:
2702
2.43M
                case 0x39:
2703
2.43M
                case 0x3A:
2704
2.43M
                case 0x3B:
2705
2.43M
                case 0x3C:
2706
2.43M
                case 0x3D:
2707
2.43M
                case 0x3E:
2708
2.43M
                case 0x3F:
2709
2.43M
                case 0x40:
2710
2.43M
                case 0x41:
2711
2.43M
                case 0x42:
2712
2.43M
                case 0x43:
2713
2.43M
                case 0x44:
2714
2.43M
                case 0x45:
2715
2.43M
                case 0x46:
2716
2.43M
                case 0x47:
2717
2.43M
                case 0x48:
2718
2.43M
                case 0x49:
2719
2.43M
                case 0x4A:
2720
2.43M
                case 0x4B:
2721
2.43M
                case 0x4C:
2722
2.43M
                case 0x4D:
2723
2.43M
                case 0x4E:
2724
2.43M
                case 0x4F:
2725
2.43M
                case 0x50:
2726
2.43M
                case 0x51:
2727
2.43M
                case 0x52:
2728
2.43M
                case 0x53:
2729
2.43M
                case 0x54:
2730
2.43M
                case 0x55:
2731
2.43M
                case 0x56:
2732
2.43M
                case 0x57:
2733
2.43M
                case 0x58:
2734
2.43M
                case 0x59:
2735
2.43M
                case 0x5A:
2736
2.43M
                case 0x5B:
2737
2.43M
                case 0x5D:
2738
2.43M
                case 0x5E:
2739
2.43M
                case 0x5F:
2740
2.43M
                case 0x60:
2741
2.43M
                case 0x61:
2742
2.43M
                case 0x62:
2743
2.43M
                case 0x63:
2744
2.43M
                case 0x64:
2745
2.43M
                case 0x65:
2746
2.43M
                case 0x66:
2747
2.43M
                case 0x67:
2748
2.43M
                case 0x68:
2749
2.43M
                case 0x69:
2750
2.43M
                case 0x6A:
2751
2.43M
                case 0x6B:
2752
2.43M
                case 0x6C:
2753
2.43M
                case 0x6D:
2754
2.43M
                case 0x6E:
2755
2.43M
                case 0x6F:
2756
2.43M
                case 0x70:
2757
2.43M
                case 0x71:
2758
2.43M
                case 0x72:
2759
2.43M
                case 0x73:
2760
2.43M
                case 0x74:
2761
2.43M
                case 0x75:
2762
2.43M
                case 0x76:
2763
2.43M
                case 0x77:
2764
2.43M
                case 0x78:
2765
2.43M
                case 0x79:
2766
2.43M
                case 0x7A:
2767
2.43M
                case 0x7B:
2768
2.43M
                case 0x7C:
2769
2.43M
                case 0x7D:
2770
2.43M
                case 0x7E:
2771
2.43M
                case 0x7F:
2772
2.43M
                {
2773
2.43M
                    add(current);
2774
2.43M
                    break;
2775
2.43M
                }
2776
2.43M
2777
2.43M
                // U+0080..U+07FF: bytes C2..DF 80..BF
2778
2.43M
                case 0xC2:
2779
0
                case 0xC3:
2780
0
                case 0xC4:
2781
0
                case 0xC5:
2782
0
                case 0xC6:
2783
0
                case 0xC7:
2784
0
                case 0xC8:
2785
0
                case 0xC9:
2786
0
                case 0xCA:
2787
0
                case 0xCB:
2788
0
                case 0xCC:
2789
0
                case 0xCD:
2790
0
                case 0xCE:
2791
0
                case 0xCF:
2792
0
                case 0xD0:
2793
0
                case 0xD1:
2794
0
                case 0xD2:
2795
0
                case 0xD3:
2796
0
                case 0xD4:
2797
0
                case 0xD5:
2798
0
                case 0xD6:
2799
0
                case 0xD7:
2800
0
                case 0xD8:
2801
0
                case 0xD9:
2802
0
                case 0xDA:
2803
0
                case 0xDB:
2804
0
                case 0xDC:
2805
0
                case 0xDD:
2806
0
                case 0xDE:
2807
0
                case 0xDF:
2808
0
                {
2809
0
                    if (JSON_UNLIKELY(not next_byte_in_range({0x80, 0xBF})))
2810
0
                    {
2811
0
                        return token_type::parse_error;
2812
0
                    }
2813
0
                    break;
2814
0
                }
2815
0
2816
0
                // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
2817
0
                case 0xE0:
2818
0
                {
2819
0
                    if (JSON_UNLIKELY(not (next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
2820
0
                    {
2821
0
                        return token_type::parse_error;
2822
0
                    }
2823
0
                    break;
2824
0
                }
2825
0
2826
0
                // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
2827
0
                // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
2828
0
                case 0xE1:
2829
0
                case 0xE2:
2830
0
                case 0xE3:
2831
0
                case 0xE4:
2832
0
                case 0xE5:
2833
0
                case 0xE6:
2834
0
                case 0xE7:
2835
0
                case 0xE8:
2836
0
                case 0xE9:
2837
0
                case 0xEA:
2838
0
                case 0xEB:
2839
0
                case 0xEC:
2840
0
                case 0xEE:
2841
0
                case 0xEF:
2842
0
                {
2843
0
                    if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
2844
0
                    {
2845
0
                        return token_type::parse_error;
2846
0
                    }
2847
0
                    break;
2848
0
                }
2849
0
2850
0
                // U+D000..U+D7FF: bytes ED 80..9F 80..BF
2851
0
                case 0xED:
2852
0
                {
2853
0
                    if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
2854
0
                    {
2855
0
                        return token_type::parse_error;
2856
0
                    }
2857
0
                    break;
2858
0
                }
2859
0
2860
0
                // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
2861
0
                case 0xF0:
2862
0
                {
2863
0
                    if (JSON_UNLIKELY(not (next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
2864
0
                    {
2865
0
                        return token_type::parse_error;
2866
0
                    }
2867
0
                    break;
2868
0
                }
2869
0
2870
0
                // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
2871
0
                case 0xF1:
2872
0
                case 0xF2:
2873
0
                case 0xF3:
2874
0
                {
2875
0
                    if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
2876
0
                    {
2877
0
                        return token_type::parse_error;
2878
0
                    }
2879
0
                    break;
2880
0
                }
2881
0
2882
0
                // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
2883
0
                case 0xF4:
2884
0
                {
2885
0
                    if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
2886
0
                    {
2887
0
                        return token_type::parse_error;
2888
0
                    }
2889
0
                    break;
2890
0
                }
2891
0
2892
0
                // remaining bytes (80..C1 and F5..FF) are ill-formed
2893
0
                default:
2894
0
                {
2895
0
                    error_message = "invalid string: ill-formed UTF-8 byte";
2896
0
                    return token_type::parse_error;
2897
0
                }
2898
2.74M
            }
2899
2.74M
        }
2900
309k
    }
2901
2902
    static void strtof(float& f, const char* str, char** endptr) noexcept
2903
    {
2904
        f = std::strtof(str, endptr);
2905
    }
2906
2907
    static void strtof(double& f, const char* str, char** endptr) noexcept
2908
57.4k
    {
2909
57.4k
        f = std::strtod(str, endptr);
2910
57.4k
    }
2911
2912
    static void strtof(long double& f, const char* str, char** endptr) noexcept
2913
    {
2914
        f = std::strtold(str, endptr);
2915
    }
2916
2917
    /*!
2918
    @brief scan a number literal
2919
2920
    This function scans a string according to Sect. 6 of RFC 7159.
2921
2922
    The function is realized with a deterministic finite state machine derived
2923
    from the grammar described in RFC 7159. Starting in state "init", the
2924
    input is read and used to determined the next state. Only state "done"
2925
    accepts the number. State "error" is a trap state to model errors. In the
2926
    table below, "anything" means any character but the ones listed before.
2927
2928
    state    | 0        | 1-9      | e E      | +       | -       | .        | anything
2929
    ---------|----------|----------|----------|---------|---------|----------|-----------
2930
    init     | zero     | any1     | [error]  | [error] | minus   | [error]  | [error]
2931
    minus    | zero     | any1     | [error]  | [error] | [error] | [error]  | [error]
2932
    zero     | done     | done     | exponent | done    | done    | decimal1 | done
2933
    any1     | any1     | any1     | exponent | done    | done    | decimal1 | done
2934
    decimal1 | decimal2 | [error]  | [error]  | [error] | [error] | [error]  | [error]
2935
    decimal2 | decimal2 | decimal2 | exponent | done    | done    | done     | done
2936
    exponent | any2     | any2     | [error]  | sign    | sign    | [error]  | [error]
2937
    sign     | any2     | any2     | [error]  | [error] | [error] | [error]  | [error]
2938
    any2     | any2     | any2     | done     | done    | done    | done     | done
2939
2940
    The state machine is realized with one label per state (prefixed with
2941
    "scan_number_") and `goto` statements between them. The state machine
2942
    contains cycles, but any cycle can be left when EOF is read. Therefore,
2943
    the function is guaranteed to terminate.
2944
2945
    During scanning, the read bytes are stored in token_buffer. This string is
2946
    then converted to a signed integer, an unsigned integer, or a
2947
    floating-point number.
2948
2949
    @return token_type::value_unsigned, token_type::value_integer, or
2950
            token_type::value_float if number could be successfully scanned,
2951
            token_type::parse_error otherwise
2952
2953
    @note The scanner is independent of the current locale. Internally, the
2954
          locale's decimal point is used instead of `.` to work with the
2955
          locale-dependent converters.
2956
    */
2957
    token_type scan_number()
2958
143k
    {
2959
143k
        // reset token_buffer to store the number's bytes
2960
143k
        reset();
2961
143k
2962
143k
        // the type of the parsed number; initially set to unsigned; will be
2963
143k
        // changed if minus sign, decimal point or exponent is read
2964
143k
        token_type number_type = token_type::value_unsigned;
2965
143k
2966
143k
        // state (init): we just found out we need to scan a number
2967
143k
        switch (current)
2968
143k
        {
2969
143k
            case '-':
2970
9.18k
            {
2971
9.18k
                add(current);
2972
9.18k
                goto scan_number_minus;
2973
143k
            }
2974
143k
2975
143k
            case '0':
2976
19.3k
            {
2977
19.3k
                add(current);
2978
19.3k
                goto scan_number_zero;
2979
143k
            }
2980
143k
2981
143k
            case '1':
2982
115k
            case '2':
2983
115k
            case '3':
2984
115k
            case '4':
2985
115k
            case '5':
2986
115k
            case '6':
2987
115k
            case '7':
2988
115k
            case '8':
2989
115k
            case '9':
2990
115k
            {
2991
115k
                add(current);
2992
115k
                goto scan_number_any1;
2993
115k
            }
2994
115k
2995
115k
            // LCOV_EXCL_START
2996
115k
            default:
2997
0
            {
2998
0
                // all other characters are rejected outside scan_number()
2999
0
                assert(false);
3000
0
            }
3001
143k
                // LCOV_EXCL_STOP
3002
143k
        }
3003
143k
3004
143k
scan_number_minus:
3005
9.18k
        // state: we just parsed a leading minus sign
3006
9.18k
        number_type = token_type::value_integer;
3007
9.18k
        switch (get())
3008
9.18k
        {
3009
9.18k
            case '0':
3010
0
            {
3011
0
                add(current);
3012
0
                goto scan_number_zero;
3013
9.18k
            }
3014
9.18k
3015
9.18k
            case '1':
3016
9.18k
            case '2':
3017
9.18k
            case '3':
3018
9.18k
            case '4':
3019
9.18k
            case '5':
3020
9.18k
            case '6':
3021
9.18k
            case '7':
3022
9.18k
            case '8':
3023
9.18k
            case '9':
3024
9.18k
            {
3025
9.18k
                add(current);
3026
9.18k
                goto scan_number_any1;
3027
9.18k
            }
3028
9.18k
3029
9.18k
            default:
3030
0
            {
3031
0
                error_message = "invalid number; expected digit after '-'";
3032
0
                return token_type::parse_error;
3033
19.3k
            }
3034
19.3k
        }
3035
19.3k
3036
19.3k
scan_number_zero:
3037
19.3k
        // state: we just parse a zero (maybe with a leading minus sign)
3038
19.3k
        switch (get())
3039
19.3k
        {
3040
19.3k
            case '.':
3041
199
            {
3042
199
                add(decimal_point_char);
3043
199
                goto scan_number_decimal1;
3044
19.3k
            }
3045
19.3k
3046
19.3k
            case 'e':
3047
0
            case 'E':
3048
0
            {
3049
0
                add(current);
3050
0
                goto scan_number_exponent;
3051
0
            }
3052
0
3053
19.1k
            default:
3054
19.1k
                goto scan_number_done;
3055
423k
        }
3056
423k
3057
423k
scan_number_any1:
3058
423k
        // state: we just parsed a number 0-9 (maybe with a leading minus sign)
3059
423k
        switch (get())
3060
423k
        {
3061
423k
            case '0':
3062
299k
            case '1':
3063
299k
            case '2':
3064
299k
            case '3':
3065
299k
            case '4':
3066
299k
            case '5':
3067
299k
            case '6':
3068
299k
            case '7':
3069
299k
            case '8':
3070
299k
            case '9':
3071
299k
            {
3072
299k
                add(current);
3073
299k
                goto scan_number_any1;
3074
299k
            }
3075
299k
3076
299k
            case '.':
3077
57.2k
            {
3078
57.2k
                add(decimal_point_char);
3079
57.2k
                goto scan_number_decimal1;
3080
299k
            }
3081
299k
3082
299k
            case 'e':
3083
0
            case 'E':
3084
0
            {
3085
0
                add(current);
3086
0
                goto scan_number_exponent;
3087
0
            }
3088
0
3089
67.0k
            default:
3090
67.0k
                goto scan_number_done;
3091
57.4k
        }
3092
57.4k
3093
57.4k
scan_number_decimal1:
3094
57.4k
        // state: we just parsed a decimal point
3095
57.4k
        number_type = token_type::value_float;
3096
57.4k
        switch (get())
3097
57.4k
        {
3098
57.4k
            case '0':
3099
57.4k
            case '1':
3100
57.4k
            case '2':
3101
57.4k
            case '3':
3102
57.4k
            case '4':
3103
57.4k
            case '5':
3104
57.4k
            case '6':
3105
57.4k
            case '7':
3106
57.4k
            case '8':
3107
57.4k
            case '9':
3108
57.4k
            {
3109
57.4k
                add(current);
3110
57.4k
                goto scan_number_decimal2;
3111
57.4k
            }
3112
57.4k
3113
57.4k
            default:
3114
0
            {
3115
0
                error_message = "invalid number; expected digit after '.'";
3116
0
                return token_type::parse_error;
3117
245k
            }
3118
245k
        }
3119
245k
3120
245k
scan_number_decimal2:
3121
245k
        // we just parsed at least one number after a decimal point
3122
245k
        switch (get())
3123
245k
        {
3124
245k
            case '0':
3125
188k
            case '1':
3126
188k
            case '2':
3127
188k
            case '3':
3128
188k
            case '4':
3129
188k
            case '5':
3130
188k
            case '6':
3131
188k
            case '7':
3132
188k
            case '8':
3133
188k
            case '9':
3134
188k
            {
3135
188k
                add(current);
3136
188k
                goto scan_number_decimal2;
3137
188k
            }
3138
188k
3139
188k
            case 'e':
3140
0
            case 'E':
3141
0
            {
3142
0
                add(current);
3143
0
                goto scan_number_exponent;
3144
0
            }
3145
0
3146
57.4k
            default:
3147
57.4k
                goto scan_number_done;
3148
0
        }
3149
0
3150
0
scan_number_exponent:
3151
0
        // we just parsed an exponent
3152
0
        number_type = token_type::value_float;
3153
0
        switch (get())
3154
0
        {
3155
0
            case '+':
3156
0
            case '-':
3157
0
            {
3158
0
                add(current);
3159
0
                goto scan_number_sign;
3160
0
            }
3161
0
3162
0
            case '0':
3163
0
            case '1':
3164
0
            case '2':
3165
0
            case '3':
3166
0
            case '4':
3167
0
            case '5':
3168
0
            case '6':
3169
0
            case '7':
3170
0
            case '8':
3171
0
            case '9':
3172
0
            {
3173
0
                add(current);
3174
0
                goto scan_number_any2;
3175
0
            }
3176
0
3177
0
            default:
3178
0
            {
3179
0
                error_message =
3180
0
                    "invalid number; expected '+', '-', or digit after exponent";
3181
0
                return token_type::parse_error;
3182
0
            }
3183
0
        }
3184
0
3185
0
scan_number_sign:
3186
0
        // we just parsed an exponent sign
3187
0
        switch (get())
3188
0
        {
3189
0
            case '0':
3190
0
            case '1':
3191
0
            case '2':
3192
0
            case '3':
3193
0
            case '4':
3194
0
            case '5':
3195
0
            case '6':
3196
0
            case '7':
3197
0
            case '8':
3198
0
            case '9':
3199
0
            {
3200
0
                add(current);
3201
0
                goto scan_number_any2;
3202
0
            }
3203
0
3204
0
            default:
3205
0
            {
3206
0
                error_message = "invalid number; expected digit after exponent sign";
3207
0
                return token_type::parse_error;
3208
0
            }
3209
0
        }
3210
0
3211
0
scan_number_any2:
3212
0
        // we just parsed a number after the exponent or exponent sign
3213
0
        switch (get())
3214
0
        {
3215
0
            case '0':
3216
0
            case '1':
3217
0
            case '2':
3218
0
            case '3':
3219
0
            case '4':
3220
0
            case '5':
3221
0
            case '6':
3222
0
            case '7':
3223
0
            case '8':
3224
0
            case '9':
3225
0
            {
3226
0
                add(current);
3227
0
                goto scan_number_any2;
3228
0
            }
3229
0
3230
0
            default:
3231
0
                goto scan_number_done;
3232
143k
        }
3233
143k
3234
143k
scan_number_done:
3235
143k
        // unget the character after the number (we only read it to know that
3236
143k
        // we are done scanning a number)
3237
143k
        unget();
3238
143k
3239
143k
        char* endptr = nullptr;
3240
143k
        errno = 0;
3241
143k
3242
143k
        // try to parse integers first and fall back to floats
3243
143k
        if (number_type == token_type::value_unsigned)
3244
77.0k
        {
3245
77.0k
            const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
3246
77.0k
3247
77.0k
            // we checked the number format before
3248
77.0k
            assert(endptr == token_buffer.data() + token_buffer.size());
3249
77.0k
3250
77.0k
            if (errno == 0)
3251
77.0k
            {
3252
77.0k
                value_unsigned = static_cast<number_unsigned_t>(x);
3253
77.0k
                if (value_unsigned == x)
3254
77.0k
                {
3255
77.0k
                    return token_type::value_unsigned;
3256
77.0k
                }
3257
66.6k
            }
3258
66.6k
        }
3259
66.6k
        else if (number_type == token_type::value_integer)
3260
9.18k
        {
3261
9.18k
            const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
3262
9.18k
3263
9.18k
            // we checked the number format before
3264
9.18k
            assert(endptr == token_buffer.data() + token_buffer.size());
3265
9.18k
3266
9.18k
            if (errno == 0)
3267
9.18k
            {
3268
9.18k
                value_integer = static_cast<number_integer_t>(x);
3269
9.18k
                if (value_integer == x)
3270
9.18k
                {
3271
9.18k
                    return token_type::value_integer;
3272
9.18k
                }
3273
57.4k
            }
3274
9.18k
        }
3275
57.4k
3276
57.4k
        // this code is reached if we parse a floating-point number or if an
3277
57.4k
        // integer conversion above failed
3278
57.4k
        strtof(value_float, token_buffer.data(), &endptr);
3279
57.4k
3280
57.4k
        // we checked the number format before
3281
57.4k
        assert(endptr == token_buffer.data() + token_buffer.size());
3282
57.4k
3283
57.4k
        return token_type::value_float;
3284
57.4k
    }
3285
3286
    /*!
3287
    @param[in] literal_text  the literal text to expect
3288
    @param[in] length        the length of the passed literal text
3289
    @param[in] return_type   the token type to return on success
3290
    */
3291
    token_type scan_literal(const char* literal_text, const std::size_t length,
3292
                            token_type return_type)
3293
1.00k
    {
3294
1.00k
        assert(current == literal_text[0]);
3295
4.01k
        for (std::size_t i = 1; i < length; ++i)
3296
3.01k
        {
3297
3.01k
            if (JSON_UNLIKELY(get() != literal_text[i]))
3298
3.01k
            {
3299
0
                error_message = "invalid literal";
3300
0
                return token_type::parse_error;
3301
0
            }
3302
3.01k
        }
3303
1.00k
        return return_type;
3304
1.00k
    }
3305
3306
    /////////////////////
3307
    // input management
3308
    /////////////////////
3309
3310
    /// reset token_buffer; current character is beginning of token
3311
    void reset() noexcept
3312
453k
    {
3313
453k
        token_buffer.clear();
3314
453k
        token_string.clear();
3315
453k
        token_string.push_back(std::char_traits<char>::to_char_type(current));
3316
453k
    }
3317
3318
    /*
3319
    @brief get next character from the input
3320
3321
    This function provides the interface to the used input adapter. It does
3322
    not throw in case the input reached EOF, but returns a
3323
    `std::char_traits<char>::eof()` in that case.  Stores the scanned characters
3324
    for use in error messages.
3325
3326
    @return character read from the input
3327
    */
3328
    std::char_traits<char>::int_type get()
3329
4.71M
    {
3330
4.71M
        ++chars_read;
3331
4.71M
        if (next_unget)
3332
144k
        {
3333
144k
            // just reset the next_unget variable and work with current
3334
144k
            next_unget = false;
3335
144k
        }
3336
4.57M
        else
3337
4.57M
        {
3338
4.57M
            current = ia->get_character();
3339
4.57M
        }
3340
4.71M
3341
4.71M
        if (JSON_LIKELY(current != std::char_traits<char>::eof()))
3342
4.71M
        {
3343
4.71M
            token_string.push_back(std::char_traits<char>::to_char_type(current));
3344
4.71M
        }
3345
4.71M
        return current;
3346
4.71M
    }
3347
3348
    /*!
3349
    @brief unget current character (read it again on next get)
3350
3351
    We implement unget by setting variable next_unget to true. The input is not
3352
    changed - we just simulate ungetting by modifying chars_read and
3353
    token_string. The next call to get() will behave as if the unget character
3354
    is read again.
3355
    */
3356
    void unget()
3357
144k
    {
3358
144k
        next_unget = true;
3359
144k
        --chars_read;
3360
144k
        if (JSON_LIKELY(current != std::char_traits<char>::eof()))
3361
144k
        {
3362
144k
            assert(token_string.size() != 0);
3363
144k
            token_string.pop_back();
3364
144k
        }
3365
144k
    }
3366
3367
    /// add a character to token_buffer
3368
    void add(int c)
3369
3.18M
    {
3370
3.18M
        token_buffer.push_back(std::char_traits<char>::to_char_type(c));
3371
3.18M
    }
3372
3373
  public:
3374
    /////////////////////
3375
    // value getters
3376
    /////////////////////
3377
3378
    /// return integer value
3379
    constexpr number_integer_t get_number_integer() const noexcept
3380
9.18k
    {
3381
9.18k
        return value_integer;
3382
9.18k
    }
3383
3384
    /// return unsigned integer value
3385
    constexpr number_unsigned_t get_number_unsigned() const noexcept
3386
77.0k
    {
3387
77.0k
        return value_unsigned;
3388
77.0k
    }
3389
3390
    /// return floating-point value
3391
    constexpr number_float_t get_number_float() const noexcept
3392
57.4k
    {
3393
57.4k
        return value_float;
3394
57.4k
    }
3395
3396
    /// return current string value (implicitly resets the token; useful only once)
3397
    string_t& get_string()
3398
366k
    {
3399
366k
        return token_buffer;
3400
366k
    }
3401
3402
    /////////////////////
3403
    // diagnostics
3404
    /////////////////////
3405
3406
    /// return position of last read token
3407
    constexpr std::size_t get_position() const noexcept
3408
2
    {
3409
2
        return chars_read;
3410
2
    }
3411
3412
    /// return the last read token (for errors only).  Will never contain EOF
3413
    /// (an arbitrary value that is not a valid char value, often -1), because
3414
    /// 255 may legitimately occur.  May contain NUL, which should be escaped.
3415
    std::string get_token_string() const
3416
1
    {
3417
1
        // escape control characters
3418
1
        std::string result;
3419
1
        for (const auto c : token_string)
3420
0
        {
3421
0
            if ('\x00' <= c and c <= '\x1F')
3422
0
            {
3423
0
                // escape control characters
3424
0
                char cs[9];
3425
0
                snprintf(cs, 9, "<U+%.4X>", static_cast<unsigned char>(c));
3426
0
                result += cs;
3427
0
            }
3428
0
            else
3429
0
            {
3430
0
                // add character as is
3431
0
                result.push_back(c);
3432
0
            }
3433
0
        }
3434
1
3435
1
        return result;
3436
1
    }
3437
3438
    /// return syntax error message
3439
    constexpr const char* get_error_message() const noexcept
3440
0
    {
3441
0
        return error_message;
3442
0
    }
3443
3444
    /////////////////////
3445
    // actual scanner
3446
    /////////////////////
3447
3448
    /*!
3449
    @brief skip the UTF-8 byte order mark
3450
    @return true iff there is no BOM or the correct BOM has been skipped
3451
    */
3452
    bool skip_bom()
3453
835
    {
3454
835
        if (get() == 0xEF)
3455
0
        {
3456
0
            if (get() == 0xBB and get() == 0xBF)
3457
0
            {
3458
0
                // we completely parsed the BOM
3459
0
                return true;
3460
0
            }
3461
0
            else
3462
0
            {
3463
0
                // after reading 0xEF, an unexpected character followed
3464
0
                return false;
3465
0
            }
3466
835
        }
3467
835
        else
3468
835
        {
3469
835
            // the first character is not the beginning of the BOM; unget it to
3470
835
            // process is later
3471
835
            unget();
3472
835
            return true;
3473
835
        }
3474
835
    }
3475
3476
    token_type scan()
3477
1.01M
    {
3478
1.01M
        // initially, skip the BOM
3479
1.01M
        if (chars_read == 0 and not skip_bom())
3480
0
        {
3481
0
            error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
3482
0
            return token_type::parse_error;
3483
0
        }
3484
1.01M
3485
1.01M
        // read next character and ignore whitespace
3486
1.01M
        do
3487
1.21M
        {
3488
1.21M
            get();
3489
1.21M
        }
3490
1.21M
        while (current == ' ' or current == '\t' or current == '\n' or current == '\r');
3491
1.01M
3492
1.01M
        switch (current)
3493
1.01M
        {
3494
1.01M
            // structural characters
3495
1.01M
            case '[':
3496
601
                return token_type::begin_array;
3497
1.01M
            case ']':
3498
601
                return token_type::end_array;
3499
1.01M
            case '{':
3500
50.8k
                return token_type::begin_object;
3501
1.01M
            case '}':
3502
50.8k
                return token_type::end_object;
3503
1.01M
            case ':':
3504
247k
                return token_type::name_separator;
3505
1.01M
            case ',':
3506
205k
                return token_type::value_separator;
3507
1.01M
3508
1.01M
            // literals
3509
1.01M
            case 't':
3510
602
                return scan_literal("true", 4, token_type::literal_true);
3511
1.01M
            case 'f':
3512
0
                return scan_literal("false", 5, token_type::literal_false);
3513
1.01M
            case 'n':
3514
402
                return scan_literal("null", 4, token_type::literal_null);
3515
1.01M
3516
1.01M
            // string
3517
1.01M
            case '\"':
3518
309k
                return scan_string();
3519
1.01M
3520
1.01M
            // number
3521
1.01M
            case '-':
3522
143k
            case '0':
3523
143k
            case '1':
3524
143k
            case '2':
3525
143k
            case '3':
3526
143k
            case '4':
3527
143k
            case '5':
3528
143k
            case '6':
3529
143k
            case '7':
3530
143k
            case '8':
3531
143k
            case '9':
3532
143k
                return scan_number();
3533
143k
3534
143k
            // end of input (the null byte is needed when parsing from
3535
143k
            // string literals)
3536
143k
            case '\0':
3537
638
            case std::char_traits<char>::eof():
3538
638
                return token_type::end_of_input;
3539
638
3540
638
            // error
3541
638
            default:
3542
0
                error_message = "invalid literal";
3543
0
                return token_type::parse_error;
3544
0
        }
3545
0
    }
3546
3547
  private:
3548
    /// input adapter
3549
    detail::input_adapter_t ia = nullptr;
3550
3551
    /// the current character
3552
    std::char_traits<char>::int_type current = std::char_traits<char>::eof();
3553
3554
    /// whether the next get() call should just return current
3555
    bool next_unget = false;
3556
3557
    /// the number of characters read
3558
    std::size_t chars_read = 0;
3559
3560
    /// raw input token string (for error messages)
3561
    std::vector<char> token_string {};
3562
3563
    /// buffer for variable-length tokens (numbers, strings)
3564
    string_t token_buffer {};
3565
3566
    /// a description of occurred lexer errors
3567
    const char* error_message = "";
3568
3569
    // number values
3570
    number_integer_t value_integer = 0;
3571
    number_unsigned_t value_unsigned = 0;
3572
    number_float_t value_float = 0;
3573
3574
    /// the decimal point
3575
    const char decimal_point_char = '.';
3576
};
3577
}
3578
}
3579
3580
// #include <nlohmann/detail/input/parser.hpp>
3581
3582
3583
#include <cassert> // assert
3584
#include <cmath> // isfinite
3585
#include <cstdint> // uint8_t
3586
#include <functional> // function
3587
#include <string> // string
3588
#include <utility> // move
3589
3590
// #include <nlohmann/detail/exceptions.hpp>
3591
3592
// #include <nlohmann/detail/macro_scope.hpp>
3593
3594
// #include <nlohmann/detail/meta/is_sax.hpp>
3595
3596
3597
#include <cstdint> // size_t
3598
#include <utility> // declval
3599
3600
// #include <nlohmann/detail/meta/detected.hpp>
3601
3602
// #include <nlohmann/detail/meta/type_traits.hpp>
3603
3604
3605
namespace nlohmann
3606
{
3607
namespace detail
3608
{
3609
template <typename T>
3610
using null_function_t = decltype(std::declval<T&>().null());
3611
3612
template <typename T>
3613
using boolean_function_t =
3614
    decltype(std::declval<T&>().boolean(std::declval<bool>()));
3615
3616
template <typename T, typename Integer>
3617
using number_integer_function_t =
3618
    decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
3619
3620
template <typename T, typename Unsigned>
3621
using number_unsigned_function_t =
3622
    decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
3623
3624
template <typename T, typename Float, typename String>
3625
using number_float_function_t = decltype(std::declval<T&>().number_float(
3626
                                    std::declval<Float>(), std::declval<const String&>()));
3627
3628
template <typename T, typename String>
3629
using string_function_t =
3630
    decltype(std::declval<T&>().string(std::declval<String&>()));
3631
3632
template <typename T>
3633
using start_object_function_t =
3634
    decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
3635
3636
template <typename T, typename String>
3637
using key_function_t =
3638
    decltype(std::declval<T&>().key(std::declval<String&>()));
3639
3640
template <typename T>
3641
using end_object_function_t = decltype(std::declval<T&>().end_object());
3642
3643
template <typename T>
3644
using start_array_function_t =
3645
    decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
3646
3647
template <typename T>
3648
using end_array_function_t = decltype(std::declval<T&>().end_array());
3649
3650
template <typename T, typename Exception>
3651
using parse_error_function_t = decltype(std::declval<T&>().parse_error(
3652
        std::declval<std::size_t>(), std::declval<const std::string&>(),
3653
        std::declval<const Exception&>()));
3654
3655
template <typename SAX, typename BasicJsonType>
3656
struct is_sax
3657
{
3658
  private:
3659
    static_assert(is_basic_json<BasicJsonType>::value,
3660
                  "BasicJsonType must be of type basic_json<...>");
3661
3662
    using number_integer_t = typename BasicJsonType::number_integer_t;
3663
    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
3664
    using number_float_t = typename BasicJsonType::number_float_t;
3665
    using string_t = typename BasicJsonType::string_t;
3666
    using exception_t = typename BasicJsonType::exception;
3667
3668
  public:
3669
    static constexpr bool value =
3670
        is_detected_exact<bool, null_function_t, SAX>::value &&
3671
        is_detected_exact<bool, boolean_function_t, SAX>::value &&
3672
        is_detected_exact<bool, number_integer_function_t, SAX,
3673
        number_integer_t>::value &&
3674
        is_detected_exact<bool, number_unsigned_function_t, SAX,
3675
        number_unsigned_t>::value &&
3676
        is_detected_exact<bool, number_float_function_t, SAX, number_float_t,
3677
        string_t>::value &&
3678
        is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
3679
        is_detected_exact<bool, start_object_function_t, SAX>::value &&
3680
        is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
3681
        is_detected_exact<bool, end_object_function_t, SAX>::value &&
3682
        is_detected_exact<bool, start_array_function_t, SAX>::value &&
3683
        is_detected_exact<bool, end_array_function_t, SAX>::value &&
3684
        is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
3685
};
3686
3687
template <typename SAX, typename BasicJsonType>
3688
struct is_sax_static_asserts
3689
{
3690
  private:
3691
    static_assert(is_basic_json<BasicJsonType>::value,
3692
                  "BasicJsonType must be of type basic_json<...>");
3693
3694
    using number_integer_t = typename BasicJsonType::number_integer_t;
3695
    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
3696
    using number_float_t = typename BasicJsonType::number_float_t;
3697
    using string_t = typename BasicJsonType::string_t;
3698
    using exception_t = typename BasicJsonType::exception;
3699
3700
  public:
3701
    static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
3702
                  "Missing/invalid function: bool null()");
3703
    static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
3704
                  "Missing/invalid function: bool boolean(bool)");
3705
    static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
3706
                  "Missing/invalid function: bool boolean(bool)");
3707
    static_assert(
3708
        is_detected_exact<bool, number_integer_function_t, SAX,
3709
        number_integer_t>::value,
3710
        "Missing/invalid function: bool number_integer(number_integer_t)");
3711
    static_assert(
3712
        is_detected_exact<bool, number_unsigned_function_t, SAX,
3713
        number_unsigned_t>::value,
3714
        "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
3715
    static_assert(is_detected_exact<bool, number_float_function_t, SAX,
3716
                  number_float_t, string_t>::value,
3717
                  "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
3718
    static_assert(
3719
        is_detected_exact<bool, string_function_t, SAX, string_t>::value,
3720
        "Missing/invalid function: bool string(string_t&)");
3721
    static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
3722
                  "Missing/invalid function: bool start_object(std::size_t)");
3723
    static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
3724
                  "Missing/invalid function: bool key(string_t&)");
3725
    static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
3726
                  "Missing/invalid function: bool end_object()");
3727
    static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
3728
                  "Missing/invalid function: bool start_array(std::size_t)");
3729
    static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
3730
                  "Missing/invalid function: bool end_array()");
3731
    static_assert(
3732
        is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
3733
        "Missing/invalid function: bool parse_error(std::size_t, const "
3734
        "std::string&, const exception&)");
3735
};
3736
}
3737
}
3738
3739
// #include <nlohmann/detail/input/input_adapters.hpp>
3740
3741
// #include <nlohmann/detail/input/json_sax.hpp>
3742
3743
3744
#include <cstddef>
3745
#include <string>
3746
#include <vector>
3747
3748
// #include <nlohmann/detail/input/parser.hpp>
3749
3750
// #include <nlohmann/detail/exceptions.hpp>
3751
3752
3753
namespace nlohmann
3754
{
3755
3756
/*!
3757
@brief SAX interface
3758
3759
This class describes the SAX interface used by @ref nlohmann::json::sax_parse.
3760
Each function is called in different situations while the input is parsed. The
3761
boolean return value informs the parser whether to continue processing the
3762
input.
3763
*/
3764
template<typename BasicJsonType>
3765
struct json_sax
3766
{
3767
    /// type for (signed) integers
3768
    using number_integer_t = typename BasicJsonType::number_integer_t;
3769
    /// type for unsigned integers
3770
    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
3771
    /// type for floating-point numbers
3772
    using number_float_t = typename BasicJsonType::number_float_t;
3773
    /// type for strings
3774
    using string_t = typename BasicJsonType::string_t;
3775
3776
    /*!
3777
    @brief a null value was read
3778
    @return whether parsing should proceed
3779
    */
3780
    virtual bool null() = 0;
3781
3782
    /*!
3783
    @brief a boolean value was read
3784
    @param[in] val  boolean value
3785
    @return whether parsing should proceed
3786
    */
3787
    virtual bool boolean(bool val) = 0;
3788
3789
    /*!
3790
    @brief an integer number was read
3791
    @param[in] val  integer value
3792
    @return whether parsing should proceed
3793
    */
3794
    virtual bool number_integer(number_integer_t val) = 0;
3795
3796
    /*!
3797
    @brief an unsigned integer number was read
3798
    @param[in] val  unsigned integer value
3799
    @return whether parsing should proceed
3800
    */
3801
    virtual bool number_unsigned(number_unsigned_t val) = 0;
3802
3803
    /*!
3804
    @brief an floating-point number was read
3805
    @param[in] val  floating-point value
3806
    @param[in] s    raw token value
3807
    @return whether parsing should proceed
3808
    */
3809
    virtual bool number_float(number_float_t val, const string_t& s) = 0;
3810
3811
    /*!
3812
    @brief a string was read
3813
    @param[in] val  string value
3814
    @return whether parsing should proceed
3815
    @note It is safe to move the passed string.
3816
    */
3817
    virtual bool string(string_t& val) = 0;
3818
3819
    /*!
3820
    @brief the beginning of an object was read
3821
    @param[in] elements  number of object elements or -1 if unknown
3822
    @return whether parsing should proceed
3823
    @note binary formats may report the number of elements
3824
    */
3825
    virtual bool start_object(std::size_t elements) = 0;
3826
3827
    /*!
3828
    @brief an object key was read
3829
    @param[in] val  object key
3830
    @return whether parsing should proceed
3831
    @note It is safe to move the passed string.
3832
    */
3833
    virtual bool key(string_t& val) = 0;
3834
3835
    /*!
3836
    @brief the end of an object was read
3837
    @return whether parsing should proceed
3838
    */
3839
    virtual bool end_object() = 0;
3840
3841
    /*!
3842
    @brief the beginning of an array was read
3843
    @param[in] elements  number of array elements or -1 if unknown
3844
    @return whether parsing should proceed
3845
    @note binary formats may report the number of elements
3846
    */
3847
    virtual bool start_array(std::size_t elements) = 0;
3848
3849
    /*!
3850
    @brief the end of an array was read
3851
    @return whether parsing should proceed
3852
    */
3853
    virtual bool end_array() = 0;
3854
3855
    /*!
3856
    @brief a parse error occurred
3857
    @param[in] position    the position in the input where the error occurs
3858
    @param[in] last_token  the last read token
3859
    @param[in] error_msg   a detailed error message
3860
    @return whether parsing should proceed (must return false)
3861
    */
3862
    virtual bool parse_error(std::size_t position,
3863
                             const std::string& last_token,
3864
                             const detail::exception& ex) = 0;
3865
3866
    virtual ~json_sax() = default;
3867
};
3868
3869
3870
namespace detail
3871
{
3872
/*!
3873
@brief SAX implementation to create a JSON value from SAX events
3874
3875
This class implements the @ref json_sax interface and processes the SAX events
3876
to create a JSON value which makes it basically a DOM parser. The structure or
3877
hierarchy of the JSON value is managed by the stack `ref_stack` which contains
3878
a pointer to the respective array or object for each recursion depth.
3879
3880
After successful parsing, the value that is passed by reference to the
3881
constructor contains the parsed value.
3882
3883
@tparam BasicJsonType  the JSON type
3884
*/
3885
template<typename BasicJsonType>
3886
class json_sax_dom_parser
3887
{
3888
  public:
3889
    using number_integer_t = typename BasicJsonType::number_integer_t;
3890
    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
3891
    using number_float_t = typename BasicJsonType::number_float_t;
3892
    using string_t = typename BasicJsonType::string_t;
3893
3894
    /*!
3895
    @param[in, out] r  reference to a JSON value that is manipulated while
3896
                       parsing
3897
    @param[in] allow_exceptions_  whether parse errors yield exceptions
3898
    */
3899
    explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
3900
        : root(r), allow_exceptions(allow_exceptions_)
3901
835
    {}
3902
3903
    bool null()
3904
402
    {
3905
402
        handle_value(nullptr);
3906
402
        return true;
3907
402
    }
3908
3909
    bool boolean(bool val)
3910
602
    {
3911
602
        handle_value(val);
3912
602
        return true;
3913
602
    }
3914
3915
    bool number_integer(number_integer_t val)
3916
9.18k
    {
3917
9.18k
        handle_value(val);
3918
9.18k
        return true;
3919
9.18k
    }
3920
3921
    bool number_unsigned(number_unsigned_t val)
3922
77.0k
    {
3923
77.0k
        handle_value(val);
3924
77.0k
        return true;
3925
77.0k
    }
3926
3927
    bool number_float(number_float_t val, const string_t&)
3928
57.4k
    {
3929
57.4k
        handle_value(val);
3930
57.4k
        return true;
3931
57.4k
    }
3932
3933
    bool string(string_t& val)
3934
61.8k
    {
3935
61.8k
        handle_value(val);
3936
61.8k
        return true;
3937
61.8k
    }
3938
3939
    bool start_object(std::size_t len)
3940
50.8k
    {
3941
50.8k
        ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
3942
50.8k
3943
50.8k
        if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
3944
50.8k
        {
3945
0
            JSON_THROW(out_of_range::create(408,
3946
0
                                            "excessive object size: " + std::to_string(len)));
3947
0
        }
3948
50.8k
3949
50.8k
        return true;
3950
50.8k
    }
3951
3952
    bool key(string_t& val)
3953
247k
    {
3954
247k
        // add null at given key and store the reference for later
3955
247k
        object_element = &(ref_stack.back()->m_value.object->operator[](val));
3956
247k
        return true;
3957
247k
    }
3958
3959
    bool end_object()
3960
50.8k
    {
3961
50.8k
        ref_stack.pop_back();
3962
50.8k
        return true;
3963
50.8k
    }
3964
3965
    bool start_array(std::size_t len)
3966
601
    {
3967
601
        ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
3968
601
3969
601
        if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
3970
601
        {
3971
0
            JSON_THROW(out_of_range::create(408,
3972
0
                                            "excessive array size: " + std::to_string(len)));
3973
0
        }
3974
601
3975
601
        return true;
3976
601
    }
3977
3978
    bool end_array()
3979
601
    {
3980
601
        ref_stack.pop_back();
3981
601
        return true;
3982
601
    }
3983
3984
    bool parse_error(std::size_t, const std::string&,
3985
                     const detail::exception& ex)
3986
1
    {
3987
1
        errored = true;
3988
1
        if (allow_exceptions)
3989
1
        {
3990
1
            // determine the proper exception type from the id
3991
1
            switch ((ex.id / 100) % 100)
3992
1
            {
3993
1
                case 1:
3994
1
                    JSON_THROW(*reinterpret_cast<const detail::parse_error*>(&ex));
3995
1
                case 4:
3996
0
                    JSON_THROW(*reinterpret_cast<const detail::out_of_range*>(&ex));
3997
1
                // LCOV_EXCL_START
3998
1
                case 2:
3999
0
                    JSON_THROW(*reinterpret_cast<const detail::invalid_iterator*>(&ex));
4000
1
                case 3:
4001
0
                    JSON_THROW(*reinterpret_cast<const detail::type_error*>(&ex));
4002
1
                case 5:
4003
0
                    JSON_THROW(*reinterpret_cast<const detail::other_error*>(&ex));
4004
1
                default:
4005
0
                    assert(false);
4006
1
                    // LCOV_EXCL_STOP
4007
1
            }
4008
1
        }
4009
1
        return false;
4010
1
    }
4011
4012
    constexpr bool is_errored() const
4013
834
    {
4014
834
        return errored;
4015
834
    }
4016
4017
  private:
4018
    /*!
4019
    @invariant If the ref stack is empty, then the passed value will be the new
4020
               root.
4021
    @invariant If the ref stack contains a value, then it is an array or an
4022
               object to which we can add elements
4023
    */
4024
    template<typename Value>
4025
    BasicJsonType* handle_value(Value&& v)
4026
257k
    {
4027
257k
        if (ref_stack.empty())
4028
834
        {
4029
834
            root = BasicJsonType(std::forward<Value>(v));
4030
834
            return &root;
4031
834
        }
4032
257k
        else
4033
257k
        {
4034
257k
            assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
4035
257k
            if (ref_stack.back()->is_array())
4036
9.57k
            {
4037
9.57k
                ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
4038
9.57k
                return &(ref_stack.back()->m_value.array->back());
4039
9.57k
            }
4040
247k
            else
4041
247k
            {
4042
247k
                assert(object_element);
4043
247k
                *object_element = BasicJsonType(std::forward<Value>(v));
4044
247k
                return object_element;
4045
247k
            }
4046
0
        }
4047
0
    }
_ZN8nlohmann6detail19json_sax_dom_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEE12handle_valueINS0_7value_tEEEPSC_OT_
Line
Count
Source
4026
51.4k
    {
4027
51.4k
        if (ref_stack.empty())
4028
834
        {
4029
834
            root = BasicJsonType(std::forward<Value>(v));
4030
834
            return &root;
4031
834
        }
4032
50.6k
        else
4033
50.6k
        {
4034
50.6k
            assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
4035
50.6k
            if (ref_stack.back()->is_array())
4036
9.57k
            {
4037
9.57k
                ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
4038
9.57k
                return &(ref_stack.back()->m_value.array->back());
4039
9.57k
            }
4040
41.0k
            else
4041
41.0k
            {
4042
41.0k
                assert(object_element);
4043
41.0k
                *object_element = BasicJsonType(std::forward<Value>(v));
4044
41.0k
                return object_element;
4045
41.0k
            }
4046
0
        }
4047
0
    }
_ZN8nlohmann6detail19json_sax_dom_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEE12handle_valueIRdEEPSC_OT_
Line
Count
Source
4026
57.4k
    {
4027
57.4k
        if (ref_stack.empty())
4028
0
        {
4029
0
            root = BasicJsonType(std::forward<Value>(v));
4030
0
            return &root;
4031
0
        }
4032
57.4k
        else
4033
57.4k
        {
4034
57.4k
            assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
4035
57.4k
            if (ref_stack.back()->is_array())
4036
0
            {
4037
0
                ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
4038
0
                return &(ref_stack.back()->m_value.array->back());
4039
0
            }
4040
57.4k
            else
4041
57.4k
            {
4042
57.4k
                assert(object_element);
4043
57.4k
                *object_element = BasicJsonType(std::forward<Value>(v));
4044
57.4k
                return object_element;
4045
57.4k
            }
4046
0
        }
4047
0
    }
_ZN8nlohmann6detail19json_sax_dom_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEE12handle_valueIRbEEPSC_OT_
Line
Count
Source
4026
602
    {
4027
602
        if (ref_stack.empty())
4028
0
        {
4029
0
            root = BasicJsonType(std::forward<Value>(v));
4030
0
            return &root;
4031
0
        }
4032
602
        else
4033
602
        {
4034
602
            assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
4035
602
            if (ref_stack.back()->is_array())
4036
0
            {
4037
0
                ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
4038
0
                return &(ref_stack.back()->m_value.array->back());
4039
0
            }
4040
602
            else
4041
602
            {
4042
602
                assert(object_element);
4043
602
                *object_element = BasicJsonType(std::forward<Value>(v));
4044
602
                return object_element;
4045
602
            }
4046
0
        }
4047
0
    }
_ZN8nlohmann6detail19json_sax_dom_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEE12handle_valueIDnEEPSC_OT_
Line
Count
Source
4026
402
    {
4027
402
        if (ref_stack.empty())
4028
0
        {
4029
0
            root = BasicJsonType(std::forward<Value>(v));
4030
0
            return &root;
4031
0
        }
4032
402
        else
4033
402
        {
4034
402
            assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
4035
402
            if (ref_stack.back()->is_array())
4036
0
            {
4037
0
                ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
4038
0
                return &(ref_stack.back()->m_value.array->back());
4039
0
            }
4040
402
            else
4041
402
            {
4042
402
                assert(object_element);
4043
402
                *object_element = BasicJsonType(std::forward<Value>(v));
4044
402
                return object_element;
4045
402
            }
4046
0
        }
4047
0
    }
_ZN8nlohmann6detail19json_sax_dom_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEE12handle_valueIRlEEPSC_OT_
Line
Count
Source
4026
9.18k
    {
4027
9.18k
        if (ref_stack.empty())
4028
0
        {
4029
0
            root = BasicJsonType(std::forward<Value>(v));
4030
0
            return &root;
4031
0
        }
4032
9.18k
        else
4033
9.18k
        {
4034
9.18k
            assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
4035
9.18k
            if (ref_stack.back()->is_array())
4036
0
            {
4037
0
                ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
4038
0
                return &(ref_stack.back()->m_value.array->back());
4039
0
            }
4040
9.18k
            else
4041
9.18k
            {
4042
9.18k
                assert(object_element);
4043
9.18k
                *object_element = BasicJsonType(std::forward<Value>(v));
4044
9.18k
                return object_element;
4045
9.18k
            }
4046
0
        }
4047
0
    }
_ZN8nlohmann6detail19json_sax_dom_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEE12handle_valueIRSA_EEPSC_OT_
Line
Count
Source
4026
61.8k
    {
4027
61.8k
        if (ref_stack.empty())
4028
0
        {
4029
0
            root = BasicJsonType(std::forward<Value>(v));
4030
0
            return &root;
4031
0
        }
4032
61.8k
        else
4033
61.8k
        {
4034
61.8k
            assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
4035
61.8k
            if (ref_stack.back()->is_array())
4036
0
            {
4037
0
                ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
4038
0
                return &(ref_stack.back()->m_value.array->back());
4039
0
            }
4040
61.8k
            else
4041
61.8k
            {
4042
61.8k
                assert(object_element);
4043
61.8k
                *object_element = BasicJsonType(std::forward<Value>(v));
4044
61.8k
                return object_element;
4045
61.8k
            }
4046
0
        }
4047
0
    }
_ZN8nlohmann6detail19json_sax_dom_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEE12handle_valueIRmEEPSC_OT_
Line
Count
Source
4026
77.0k
    {
4027
77.0k
        if (ref_stack.empty())
4028
0
        {
4029
0
            root = BasicJsonType(std::forward<Value>(v));
4030
0
            return &root;
4031
0
        }
4032
77.0k
        else
4033
77.0k
        {
4034
77.0k
            assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
4035
77.0k
            if (ref_stack.back()->is_array())
4036
0
            {
4037
0
                ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
4038
0
                return &(ref_stack.back()->m_value.array->back());
4039
0
            }
4040
77.0k
            else
4041
77.0k
            {
4042
77.0k
                assert(object_element);
4043
77.0k
                *object_element = BasicJsonType(std::forward<Value>(v));
4044
77.0k
                return object_element;
4045
77.0k
            }
4046
0
        }
4047
0
    }
4048
4049
    /// the parsed JSON value
4050
    BasicJsonType& root;
4051
    /// stack to model hierarchy of values
4052
    std::vector<BasicJsonType*> ref_stack;
4053
    /// helper to hold the reference for the next object element
4054
    BasicJsonType* object_element = nullptr;
4055
    /// whether a syntax error occurred
4056
    bool errored = false;
4057
    /// whether to throw exceptions in case of errors
4058
    const bool allow_exceptions = true;
4059
};
4060
4061
template<typename BasicJsonType>
4062
class json_sax_dom_callback_parser
4063
{
4064
  public:
4065
    using number_integer_t = typename BasicJsonType::number_integer_t;
4066
    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
4067
    using number_float_t = typename BasicJsonType::number_float_t;
4068
    using string_t = typename BasicJsonType::string_t;
4069
    using parser_callback_t = typename BasicJsonType::parser_callback_t;
4070
    using parse_event_t = typename BasicJsonType::parse_event_t;
4071
4072
    json_sax_dom_callback_parser(BasicJsonType& r,
4073
                                 const parser_callback_t cb,
4074
                                 const bool allow_exceptions_ = true)
4075
        : root(r), callback(cb), allow_exceptions(allow_exceptions_)
4076
0
    {
4077
0
        keep_stack.push_back(true);
4078
0
    }
4079
4080
    bool null()
4081
0
    {
4082
0
        handle_value(nullptr);
4083
0
        return true;
4084
0
    }
4085
4086
    bool boolean(bool val)
4087
0
    {
4088
0
        handle_value(val);
4089
0
        return true;
4090
0
    }
4091
4092
    bool number_integer(number_integer_t val)
4093
0
    {
4094
0
        handle_value(val);
4095
0
        return true;
4096
0
    }
4097
4098
    bool number_unsigned(number_unsigned_t val)
4099
0
    {
4100
0
        handle_value(val);
4101
0
        return true;
4102
0
    }
4103
4104
    bool number_float(number_float_t val, const string_t&)
4105
0
    {
4106
0
        handle_value(val);
4107
0
        return true;
4108
0
    }
4109
4110
    bool string(string_t& val)
4111
0
    {
4112
0
        handle_value(val);
4113
0
        return true;
4114
0
    }
4115
4116
    bool start_object(std::size_t len)
4117
0
    {
4118
0
        // check callback for object start
4119
0
        const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
4120
0
        keep_stack.push_back(keep);
4121
0
4122
0
        auto val = handle_value(BasicJsonType::value_t::object, true);
4123
0
        ref_stack.push_back(val.second);
4124
0
4125
0
        // check object limit
4126
0
        if (ref_stack.back())
4127
0
        {
4128
0
            if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
4129
0
            {
4130
0
                JSON_THROW(out_of_range::create(408,
4131
0
                                                "excessive object size: " + std::to_string(len)));
4132
0
            }
4133
0
        }
4134
0
4135
0
        return true;
4136
0
    }
4137
4138
    bool key(string_t& val)
4139
0
    {
4140
0
        BasicJsonType k = BasicJsonType(val);
4141
0
4142
0
        // check callback for key
4143
0
        const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
4144
0
        key_keep_stack.push_back(keep);
4145
0
4146
0
        // add discarded value at given key and store the reference for later
4147
0
        if (keep and ref_stack.back())
4148
0
        {
4149
0
            object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded);
4150
0
        }
4151
0
4152
0
        return true;
4153
0
    }
4154
4155
    bool end_object()
4156
0
    {
4157
0
        if (ref_stack.back())
4158
0
        {
4159
0
            if (not callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
4160
0
            {
4161
0
                // discard object
4162
0
                *ref_stack.back() = discarded;
4163
0
            }
4164
0
        }
4165
0
4166
0
        assert(not ref_stack.empty());
4167
0
        assert(not keep_stack.empty());
4168
0
        ref_stack.pop_back();
4169
0
        keep_stack.pop_back();
4170
0
4171
0
        if (not ref_stack.empty() and ref_stack.back())
4172
0
        {
4173
0
            // remove discarded value
4174
0
            if (ref_stack.back()->is_object())
4175
0
            {
4176
0
                for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
4177
0
                {
4178
0
                    if (it->is_discarded())
4179
0
                    {
4180
0
                        ref_stack.back()->erase(it);
4181
0
                        break;
4182
0
                    }
4183
0
                }
4184
0
            }
4185
0
        }
4186
0
4187
0
        return true;
4188
0
    }
4189
4190
    bool start_array(std::size_t len)
4191
0
    {
4192
0
        const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
4193
0
        keep_stack.push_back(keep);
4194
0
4195
0
        auto val = handle_value(BasicJsonType::value_t::array, true);
4196
0
        ref_stack.push_back(val.second);
4197
0
4198
0
        // check array limit
4199
0
        if (ref_stack.back())
4200
0
        {
4201
0
            if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
4202
0
            {
4203
0
                JSON_THROW(out_of_range::create(408,
4204
0
                                                "excessive array size: " + std::to_string(len)));
4205
0
            }
4206
0
        }
4207
0
4208
0
        return true;
4209
0
    }
4210
4211
    bool end_array()
4212
0
    {
4213
0
        bool keep = true;
4214
0
4215
0
        if (ref_stack.back())
4216
0
        {
4217
0
            keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
4218
0
            if (not keep)
4219
0
            {
4220
0
                // discard array
4221
0
                *ref_stack.back() = discarded;
4222
0
            }
4223
0
        }
4224
0
4225
0
        assert(not ref_stack.empty());
4226
0
        assert(not keep_stack.empty());
4227
0
        ref_stack.pop_back();
4228
0
        keep_stack.pop_back();
4229
0
4230
0
        // remove discarded value
4231
0
        if (not keep and not ref_stack.empty())
4232
0
        {
4233
0
            if (ref_stack.back()->is_array())
4234
0
            {
4235
0
                ref_stack.back()->m_value.array->pop_back();
4236
0
            }
4237
0
        }
4238
0
4239
0
        return true;
4240
0
    }
4241
4242
    bool parse_error(std::size_t, const std::string&,
4243
                     const detail::exception& ex)
4244
0
    {
4245
0
        errored = true;
4246
0
        if (allow_exceptions)
4247
0
        {
4248
0
            // determine the proper exception type from the id
4249
0
            switch ((ex.id / 100) % 100)
4250
0
            {
4251
0
                case 1:
4252
0
                    JSON_THROW(*reinterpret_cast<const detail::parse_error*>(&ex));
4253
0
                case 4:
4254
0
                    JSON_THROW(*reinterpret_cast<const detail::out_of_range*>(&ex));
4255
0
                // LCOV_EXCL_START
4256
0
                case 2:
4257
0
                    JSON_THROW(*reinterpret_cast<const detail::invalid_iterator*>(&ex));
4258
0
                case 3:
4259
0
                    JSON_THROW(*reinterpret_cast<const detail::type_error*>(&ex));
4260
0
                case 5:
4261
0
                    JSON_THROW(*reinterpret_cast<const detail::other_error*>(&ex));
4262
0
                default:
4263
0
                    assert(false);
4264
0
                    // LCOV_EXCL_STOP
4265
0
            }
4266
0
        }
4267
0
        return false;
4268
0
    }
4269
4270
    constexpr bool is_errored() const
4271
0
    {
4272
0
        return errored;
4273
0
    }
4274
4275
  private:
4276
    /*!
4277
    @param[in] v  value to add to the JSON value we build during parsing
4278
    @param[in] skip_callback  whether we should skip calling the callback
4279
               function; this is required after start_array() and
4280
               start_object() SAX events, because otherwise we would call the
4281
               callback function with an empty array or object, respectively.
4282
4283
    @invariant If the ref stack is empty, then the passed value will be the new
4284
               root.
4285
    @invariant If the ref stack contains a value, then it is an array or an
4286
               object to which we can add elements
4287
4288
    @return pair of boolean (whether value should be kept) and pointer (to the
4289
            passed value in the ref_stack hierarchy; nullptr if not kept)
4290
    */
4291
    template<typename Value>
4292
    std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
4293
0
    {
4294
0
        assert(not keep_stack.empty());
4295
0
4296
0
        // do not handle this value if we know it would be added to a discarded
4297
0
        // container
4298
0
        if (not keep_stack.back())
4299
0
        {
4300
0
            return {false, nullptr};
4301
0
        }
4302
0
4303
0
        // create value
4304
0
        auto value = BasicJsonType(std::forward<Value>(v));
4305
0
4306
0
        // check callback
4307
0
        const bool keep = skip_callback or callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
4308
0
4309
0
        // do not handle this value if we just learnt it shall be discarded
4310
0
        if (not keep)
4311
0
        {
4312
0
            return {false, nullptr};
4313
0
        }
4314
0
4315
0
        if (ref_stack.empty())
4316
0
        {
4317
0
            root = std::move(value);
4318
0
            return {true, &root};
4319
0
        }
4320
0
        else
4321
0
        {
4322
0
            // skip this value if we already decided to skip the parent
4323
0
            // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
4324
0
            if (not ref_stack.back())
4325
0
            {
4326
0
                return {false, nullptr};
4327
0
            }
4328
0
4329
0
            assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
4330
0
            if (ref_stack.back()->is_array())
4331
0
            {
4332
0
                ref_stack.back()->m_value.array->push_back(std::move(value));
4333
0
                return {true, &(ref_stack.back()->m_value.array->back())};
4334
0
            }
4335
0
            else
4336
0
            {
4337
0
                // check if we should store an element for the current key
4338
0
                assert(not key_keep_stack.empty());
4339
0
                const bool store_element = key_keep_stack.back();
4340
0
                key_keep_stack.pop_back();
4341
0
4342
0
                if (not store_element)
4343
0
                {
4344
0
                    return {false, nullptr};
4345
0
                }
4346
0
4347
0
                assert(object_element);
4348
0
                *object_element = std::move(value);
4349
0
                return {true, object_element};
4350
0
            }
4351
0
        }
4352
0
    }
Unexecuted instantiation: _ZN8nlohmann6detail28json_sax_dom_callback_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEE12handle_valueINS0_7value_tEEESt4pairIbPSC_EOT_b
Unexecuted instantiation: _ZN8nlohmann6detail28json_sax_dom_callback_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEE12handle_valueIRdEESt4pairIbPSC_EOT_b
Unexecuted instantiation: _ZN8nlohmann6detail28json_sax_dom_callback_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEE12handle_valueIRbEESt4pairIbPSC_EOT_b
Unexecuted instantiation: _ZN8nlohmann6detail28json_sax_dom_callback_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEE12handle_valueIDnEESt4pairIbPSC_EOT_b
Unexecuted instantiation: _ZN8nlohmann6detail28json_sax_dom_callback_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEE12handle_valueIRlEESt4pairIbPSC_EOT_b
Unexecuted instantiation: _ZN8nlohmann6detail28json_sax_dom_callback_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEE12handle_valueIRSA_EESt4pairIbPSC_EOT_b
Unexecuted instantiation: _ZN8nlohmann6detail28json_sax_dom_callback_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEE12handle_valueIRmEESt4pairIbPSC_EOT_b
4353
4354
    /// the parsed JSON value
4355
    BasicJsonType& root;
4356
    /// stack to model hierarchy of values
4357
    std::vector<BasicJsonType*> ref_stack;
4358
    /// stack to manage which values to keep
4359
    std::vector<bool> keep_stack;
4360
    /// stack to manage which object keys to keep
4361
    std::vector<bool> key_keep_stack;
4362
    /// helper to hold the reference for the next object element
4363
    BasicJsonType* object_element = nullptr;
4364
    /// whether a syntax error occurred
4365
    bool errored = false;
4366
    /// callback function
4367
    const parser_callback_t callback = nullptr;
4368
    /// whether to throw exceptions in case of errors
4369
    const bool allow_exceptions = true;
4370
    /// a discarded value for the callback
4371
    BasicJsonType discarded = BasicJsonType::value_t::discarded;
4372
};
4373
4374
template<typename BasicJsonType>
4375
class json_sax_acceptor
4376
{
4377
  public:
4378
    using number_integer_t = typename BasicJsonType::number_integer_t;
4379
    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
4380
    using number_float_t = typename BasicJsonType::number_float_t;
4381
    using string_t = typename BasicJsonType::string_t;
4382
4383
    bool null()
4384
    {
4385
        return true;
4386
    }
4387
4388
    bool boolean(bool)
4389
    {
4390
        return true;
4391
    }
4392
4393
    bool number_integer(number_integer_t)
4394
    {
4395
        return true;
4396
    }
4397
4398
    bool number_unsigned(number_unsigned_t)
4399
    {
4400
        return true;
4401
    }
4402
4403
    bool number_float(number_float_t, const string_t&)
4404
    {
4405
        return true;
4406
    }
4407
4408
    bool string(string_t&)
4409
    {
4410
        return true;
4411
    }
4412
4413
    bool start_object(std::size_t = std::size_t(-1))
4414
    {
4415
        return true;
4416
    }
4417
4418
    bool key(string_t&)
4419
    {
4420
        return true;
4421
    }
4422
4423
    bool end_object()
4424
    {
4425
        return true;
4426
    }
4427
4428
    bool start_array(std::size_t = std::size_t(-1))
4429
    {
4430
        return true;
4431
    }
4432
4433
    bool end_array()
4434
    {
4435
        return true;
4436
    }
4437
4438
    bool parse_error(std::size_t, const std::string&, const detail::exception&)
4439
    {
4440
        return false;
4441
    }
4442
};
4443
}
4444
4445
}
4446
4447
// #include <nlohmann/detail/input/lexer.hpp>
4448
4449
// #include <nlohmann/detail/value_t.hpp>
4450
4451
4452
namespace nlohmann
4453
{
4454
namespace detail
4455
{
4456
////////////
4457
// parser //
4458
////////////
4459
4460
/*!
4461
@brief syntax analysis
4462
4463
This class implements a recursive decent parser.
4464
*/
4465
template<typename BasicJsonType>
4466
class parser
4467
{
4468
    using number_integer_t = typename BasicJsonType::number_integer_t;
4469
    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
4470
    using number_float_t = typename BasicJsonType::number_float_t;
4471
    using string_t = typename BasicJsonType::string_t;
4472
    using lexer_t = lexer<BasicJsonType>;
4473
    using token_type = typename lexer_t::token_type;
4474
4475
  public:
4476
    enum class parse_event_t : uint8_t
4477
    {
4478
        /// the parser read `{` and started to process a JSON object
4479
        object_start,
4480
        /// the parser read `}` and finished processing a JSON object
4481
        object_end,
4482
        /// the parser read `[` and started to process a JSON array
4483
        array_start,
4484
        /// the parser read `]` and finished processing a JSON array
4485
        array_end,
4486
        /// the parser read a key of a value in an object
4487
        key,
4488
        /// the parser finished reading a JSON value
4489
        value
4490
    };
4491
4492
    using parser_callback_t =
4493
        std::function<bool(int depth, parse_event_t event, BasicJsonType& parsed)>;
4494
4495
    /// a parser reading from an input adapter
4496
    explicit parser(detail::input_adapter_t&& adapter,
4497
                    const parser_callback_t cb = nullptr,
4498
                    const bool allow_exceptions_ = true)
4499
        : callback(cb), m_lexer(std::move(adapter)), allow_exceptions(allow_exceptions_)
4500
835
    {
4501
835
        // read first token
4502
835
        get_token();
4503
835
    }
4504
4505
    /*!
4506
    @brief public parser interface
4507
4508
    @param[in] strict      whether to expect the last token to be EOF
4509
    @param[in,out] result  parsed JSON value
4510
4511
    @throw parse_error.101 in case of an unexpected token
4512
    @throw parse_error.102 if to_unicode fails or surrogate error
4513
    @throw parse_error.103 if to_unicode fails
4514
    */
4515
    void parse(const bool strict, BasicJsonType& result)
4516
835
    {
4517
835
        if (callback)
4518
0
        {
4519
0
            json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
4520
0
            sax_parse_internal(&sdp);
4521
0
            result.assert_invariant();
4522
0
4523
0
            // in strict mode, input must be completely read
4524
0
            if (strict and (get_token() != token_type::end_of_input))
4525
0
            {
4526
0
                sdp.parse_error(m_lexer.get_position(),
4527
0
                                m_lexer.get_token_string(),
4528
0
                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input)));
4529
0
            }
4530
0
4531
0
            // in case of an error, return discarded value
4532
0
            if (sdp.is_errored())
4533
0
            {
4534
0
                result = value_t::discarded;
4535
0
                return;
4536
0
            }
4537
0
4538
0
            // set top-level value to null if it was discarded by the callback
4539
0
            // function
4540
0
            if (result.is_discarded())
4541
0
            {
4542
0
                result = nullptr;
4543
0
            }
4544
0
        }
4545
835
        else
4546
835
        {
4547
835
            json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
4548
835
            sax_parse_internal(&sdp);
4549
835
            result.assert_invariant();
4550
835
4551
835
            // in strict mode, input must be completely read
4552
835
            if (strict and (get_token() != token_type::end_of_input))
4553
0
            {
4554
0
                sdp.parse_error(m_lexer.get_position(),
4555
0
                                m_lexer.get_token_string(),
4556
0
                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input)));
4557
0
            }
4558
835
4559
835
            // in case of an error, return discarded value
4560
835
            if (sdp.is_errored())
4561
0
            {
4562
0
                result = value_t::discarded;
4563
0
                return;
4564
0
            }
4565
835
        }
4566
835
    }
4567
4568
    /*!
4569
    @brief public accept interface
4570
4571
    @param[in] strict  whether to expect the last token to be EOF
4572
    @return whether the input is a proper JSON text
4573
    */
4574
    bool accept(const bool strict = true)
4575
    {
4576
        json_sax_acceptor<BasicJsonType> sax_acceptor;
4577
        return sax_parse(&sax_acceptor, strict);
4578
    }
4579
4580
    template <typename SAX>
4581
    bool sax_parse(SAX* sax, const bool strict = true)
4582
    {
4583
        (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
4584
        const bool result = sax_parse_internal(sax);
4585
4586
        // strict mode: next byte must be EOF
4587
        if (result and strict and (get_token() != token_type::end_of_input))
4588
        {
4589
            return sax->parse_error(m_lexer.get_position(),
4590
                                    m_lexer.get_token_string(),
4591
                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input)));
4592
        }
4593
4594
        return result;
4595
    }
4596
4597
  private:
4598
    template <typename SAX>
4599
    bool sax_parse_internal(SAX* sax)
4600
835
    {
4601
835
        // stack to remember the hieararchy of structured values we are parsing
4602
835
        // true = array; false = object
4603
835
        std::vector<bool> states;
4604
835
        // value to avoid a goto (see comment where set to true)
4605
835
        bool skip_to_state_evaluation = false;
4606
835
4607
309k
        while (true)
4608
309k
        {
4609
309k
            if (not skip_to_state_evaluation)
4610
257k
            {
4611
257k
                // invariant: get_token() was called before each iteration
4612
257k
                switch (last_token)
4613
257k
                {
4614
257k
                    case token_type::begin_object:
4615
50.8k
                    {
4616
50.8k
                        if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1))))
4617
50.8k
                        {
4618
0
                            return false;
4619
0
                        }
4620
50.8k
4621
50.8k
                        // closing } -> we are done
4622
50.8k
                        if (get_token() == token_type::end_object)
4623
0
                        {
4624
0
                            if (JSON_UNLIKELY(not sax->end_object()))
4625
0
                            {
4626
0
                                return false;
4627
0
                            }
4628
0
                            break;
4629
0
                        }
4630
50.8k
4631
50.8k
                        // parse key
4632
50.8k
                        if (JSON_UNLIKELY(last_token != token_type::value_string))
4633
50.8k
                        {
4634
0
                            return sax->parse_error(m_lexer.get_position(),
4635
0
                                                    m_lexer.get_token_string(),
4636
0
                                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string)));
4637
0
                        }
4638
50.8k
                        else
4639
50.8k
                        {
4640
50.8k
                            if (JSON_UNLIKELY(not sax->key(m_lexer.get_string())))
4641
50.8k
                            {
4642
0
                                return false;
4643
0
                            }
4644
50.8k
                        }
4645
50.8k
4646
50.8k
                        // parse separator (:)
4647
50.8k
                        if (JSON_UNLIKELY(get_token() != token_type::name_separator))
4648
50.8k
                        {
4649
0
                            return sax->parse_error(m_lexer.get_position(),
4650
0
                                                    m_lexer.get_token_string(),
4651
0
                                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator)));
4652
0
                        }
4653
50.8k
4654
50.8k
                        // remember we are now inside an object
4655
50.8k
                        states.push_back(false);
4656
50.8k
4657
50.8k
                        // parse values
4658
50.8k
                        get_token();
4659
50.8k
                        continue;
4660
50.8k
                    }
4661
50.8k
4662
50.8k
                    case token_type::begin_array:
4663
601
                    {
4664
601
                        if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1))))
4665
601
                        {
4666
0
                            return false;
4667
0
                        }
4668
601
4669
601
                        // closing ] -> we are done
4670
601
                        if (get_token() == token_type::end_array)
4671
199
                        {
4672
199
                            if (JSON_UNLIKELY(not sax->end_array()))
4673
199
                            {
4674
0
                                return false;
4675
0
                            }
4676
199
                            break;
4677
199
                        }
4678
402
4679
402
                        // remember we are now inside an array
4680
402
                        states.push_back(true);
4681
402
4682
402
                        // parse values (no need to call get_token)
4683
402
                        continue;
4684
402
                    }
4685
402
4686
57.4k
                    case token_type::value_float:
4687
57.4k
                    {
4688
57.4k
                        const auto res = m_lexer.get_number_float();
4689
57.4k
4690
57.4k
                        if (JSON_UNLIKELY(not std::isfinite(res)))
4691
57.4k
                        {
4692
0
                            return sax->parse_error(m_lexer.get_position(),
4693
0
                                                    m_lexer.get_token_string(),
4694
0
                                                    out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'"));
4695
0
                        }
4696
57.4k
                        else
4697
57.4k
                        {
4698
57.4k
                            if (JSON_UNLIKELY(not sax->number_float(res, m_lexer.get_string())))
4699
57.4k
                            {
4700
0
                                return false;
4701
0
                            }
4702
57.4k
                            break;
4703
57.4k
                        }
4704
0
                    }
4705
0
4706
0
                    case token_type::literal_false:
4707
0
                    {
4708
0
                        if (JSON_UNLIKELY(not sax->boolean(false)))
4709
0
                        {
4710
0
                            return false;
4711
0
                        }
4712
0
                        break;
4713
0
                    }
4714
0
4715
402
                    case token_type::literal_null:
4716
402
                    {
4717
402
                        if (JSON_UNLIKELY(not sax->null()))
4718
402
                        {
4719
0
                            return false;
4720
0
                        }
4721
402
                        break;
4722
402
                    }
4723
402
4724
602
                    case token_type::literal_true:
4725
602
                    {
4726
602
                        if (JSON_UNLIKELY(not sax->boolean(true)))
4727
602
                        {
4728
0
                            return false;
4729
0
                        }
4730
602
                        break;
4731
602
                    }
4732
602
4733
9.18k
                    case token_type::value_integer:
4734
9.18k
                    {
4735
9.18k
                        if (JSON_UNLIKELY(not sax->number_integer(m_lexer.get_number_integer())))
4736
9.18k
                        {
4737
0
                            return false;
4738
0
                        }
4739
9.18k
                        break;
4740
9.18k
                    }
4741
9.18k
4742
61.8k
                    case token_type::value_string:
4743
61.8k
                    {
4744
61.8k
                        if (JSON_UNLIKELY(not sax->string(m_lexer.get_string())))
4745
61.8k
                        {
4746
0
                            return false;
4747
0
                        }
4748
61.8k
                        break;
4749
61.8k
                    }
4750
61.8k
4751
77.0k
                    case token_type::value_unsigned:
4752
77.0k
                    {
4753
77.0k
                        if (JSON_UNLIKELY(not sax->number_unsigned(m_lexer.get_number_unsigned())))
4754
77.0k
                        {
4755
0
                            return false;
4756
0
                        }
4757
77.0k
                        break;
4758
77.0k
                    }
4759
77.0k
4760
77.0k
                    case token_type::parse_error:
4761
0
                    {
4762
0
                        // using "uninitialized" to avoid "expected" message
4763
0
                        return sax->parse_error(m_lexer.get_position(),
4764
0
                                                m_lexer.get_token_string(),
4765
0
                                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized)));
4766
77.0k
                    }
4767
77.0k
4768
77.0k
                    default: // the last token was unexpected
4769
1
                    {
4770
1
                        return sax->parse_error(m_lexer.get_position(),
4771
1
                                                m_lexer.get_token_string(),
4772
1
                                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value)));
4773
51.2k
                    }
4774
51.2k
                }
4775
51.2k
            }
4776
51.2k
            else
4777
51.2k
            {
4778
51.2k
                skip_to_state_evaluation = false;
4779
51.2k
            }
4780
309k
4781
309k
            // we reached this line after we successfully parsed a value
4782
309k
            if (states.empty())
4783
834
            {
4784
834
                // empty stack: we reached the end of the hieararchy: done
4785
834
                return true;
4786
834
            }
4787
257k
            else
4788
257k
            {
4789
257k
                if (states.back())  // array
4790
9.57k
                {
4791
9.57k
                    // comma -> next value
4792
9.57k
                    if (get_token() == token_type::value_separator)
4793
9.17k
                    {
4794
9.17k
                        // parse a new value
4795
9.17k
                        get_token();
4796
9.17k
                        continue;
4797
9.17k
                    }
4798
402
4799
402
                    // closing ]
4800
402
                    if (JSON_LIKELY(last_token == token_type::end_array))
4801
402
                    {
4802
402
                        if (JSON_UNLIKELY(not sax->end_array()))
4803
402
                        {
4804
0
                            return false;
4805
0
                        }
4806
402
4807
402
                        // We are done with this array. Before we can parse a
4808
402
                        // new value, we need to evaluate the new state first.
4809
402
                        // By setting skip_to_state_evaluation to false, we
4810
402
                        // are effectively jumping to the beginning of this if.
4811
402
                        assert(not states.empty());
4812
402
                        states.pop_back();
4813
402
                        skip_to_state_evaluation = true;
4814
402
                        continue;
4815
402
                    }
4816
0
                    else
4817
0
                    {
4818
0
                        return sax->parse_error(m_lexer.get_position(),
4819
0
                                                m_lexer.get_token_string(),
4820
0
                                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array)));
4821
0
                    }
4822
247k
                }
4823
247k
                else  // object
4824
247k
                {
4825
247k
                    // comma -> next value
4826
247k
                    if (get_token() == token_type::value_separator)
4827
196k
                    {
4828
196k
                        // parse key
4829
196k
                        if (JSON_UNLIKELY(get_token() != token_type::value_string))
4830
196k
                        {
4831
0
                            return sax->parse_error(m_lexer.get_position(),
4832
0
                                                    m_lexer.get_token_string(),
4833
0
                                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string)));
4834
0
                        }
4835
196k
                        else
4836
196k
                        {
4837
196k
                            if (JSON_UNLIKELY(not sax->key(m_lexer.get_string())))
4838
196k
                            {
4839
0
                                return false;
4840
0
                            }
4841
196k
                        }
4842
196k
4843
196k
                        // parse separator (:)
4844
196k
                        if (JSON_UNLIKELY(get_token() != token_type::name_separator))
4845
196k
                        {
4846
0
                            return sax->parse_error(m_lexer.get_position(),
4847
0
                                                    m_lexer.get_token_string(),
4848
0
                                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator)));
4849
0
                        }
4850
196k
4851
196k
                        // parse values
4852
196k
                        get_token();
4853
196k
                        continue;
4854
196k
                    }
4855
50.8k
4856
50.8k
                    // closing }
4857
50.8k
                    if (JSON_LIKELY(last_token == token_type::end_object))
4858
50.8k
                    {
4859
50.8k
                        if (JSON_UNLIKELY(not sax->end_object()))
4860
50.8k
                        {
4861
0
                            return false;
4862
0
                        }
4863
50.8k
4864
50.8k
                        // We are done with this object. Before we can parse a
4865
50.8k
                        // new value, we need to evaluate the new state first.
4866
50.8k
                        // By setting skip_to_state_evaluation to false, we
4867
50.8k
                        // are effectively jumping to the beginning of this if.
4868
50.8k
                        assert(not states.empty());
4869
50.8k
                        states.pop_back();
4870
50.8k
                        skip_to_state_evaluation = true;
4871
50.8k
                        continue;
4872
50.8k
                    }
4873
0
                    else
4874
0
                    {
4875
0
                        return sax->parse_error(m_lexer.get_position(),
4876
0
                                                m_lexer.get_token_string(),
4877
0
                                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object)));
4878
0
                    }
4879
50.8k
                }
4880
257k
            }
4881
257k
        }
4882
835
    }
Unexecuted instantiation: _ZN8nlohmann6detail6parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEE18sax_parse_internalINS0_28json_sax_dom_callback_parserISC_EEEEbPT_
_ZN8nlohmann6detail6parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEE18sax_parse_internalINS0_19json_sax_dom_parserISC_EEEEbPT_
Line
Count
Source
4600
835
    {
4601
835
        // stack to remember the hieararchy of structured values we are parsing
4602
835
        // true = array; false = object
4603
835
        std::vector<bool> states;
4604
835
        // value to avoid a goto (see comment where set to true)
4605
835
        bool skip_to_state_evaluation = false;
4606
835
4607
309k
        while (true)
4608
309k
        {
4609
309k
            if (not skip_to_state_evaluation)
4610
257k
            {
4611
257k
                // invariant: get_token() was called before each iteration
4612
257k
                switch (last_token)
4613
257k
                {
4614
257k
                    case token_type::begin_object:
4615
50.8k
                    {
4616
50.8k
                        if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1))))
4617
50.8k
                        {
4618
0
                            return false;
4619
0
                        }
4620
50.8k
4621
50.8k
                        // closing } -> we are done
4622
50.8k
                        if (get_token() == token_type::end_object)
4623
0
                        {
4624
0
                            if (JSON_UNLIKELY(not sax->end_object()))
4625
0
                            {
4626
0
                                return false;
4627
0
                            }
4628
0
                            break;
4629
0
                        }
4630
50.8k
4631
50.8k
                        // parse key
4632
50.8k
                        if (JSON_UNLIKELY(last_token != token_type::value_string))
4633
50.8k
                        {
4634
0
                            return sax->parse_error(m_lexer.get_position(),
4635
0
                                                    m_lexer.get_token_string(),
4636
0
                                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string)));
4637
0
                        }
4638
50.8k
                        else
4639
50.8k
                        {
4640
50.8k
                            if (JSON_UNLIKELY(not sax->key(m_lexer.get_string())))
4641
50.8k
                            {
4642
0
                                return false;
4643
0
                            }
4644
50.8k
                        }
4645
50.8k
4646
50.8k
                        // parse separator (:)
4647
50.8k
                        if (JSON_UNLIKELY(get_token() != token_type::name_separator))
4648
50.8k
                        {
4649
0
                            return sax->parse_error(m_lexer.get_position(),
4650
0
                                                    m_lexer.get_token_string(),
4651
0
                                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator)));
4652
0
                        }
4653
50.8k
4654
50.8k
                        // remember we are now inside an object
4655
50.8k
                        states.push_back(false);
4656
50.8k
4657
50.8k
                        // parse values
4658
50.8k
                        get_token();
4659
50.8k
                        continue;
4660
50.8k
                    }
4661
50.8k
4662
50.8k
                    case token_type::begin_array:
4663
601
                    {
4664
601
                        if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1))))
4665
601
                        {
4666
0
                            return false;
4667
0
                        }
4668
601
4669
601
                        // closing ] -> we are done
4670
601
                        if (get_token() == token_type::end_array)
4671
199
                        {
4672
199
                            if (JSON_UNLIKELY(not sax->end_array()))
4673
199
                            {
4674
0
                                return false;
4675
0
                            }
4676
199
                            break;
4677
199
                        }
4678
402
4679
402
                        // remember we are now inside an array
4680
402
                        states.push_back(true);
4681
402
4682
402
                        // parse values (no need to call get_token)
4683
402
                        continue;
4684
402
                    }
4685
402
4686
57.4k
                    case token_type::value_float:
4687
57.4k
                    {
4688
57.4k
                        const auto res = m_lexer.get_number_float();
4689
57.4k
4690
57.4k
                        if (JSON_UNLIKELY(not std::isfinite(res)))
4691
57.4k
                        {
4692
0
                            return sax->parse_error(m_lexer.get_position(),
4693
0
                                                    m_lexer.get_token_string(),
4694
0
                                                    out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'"));
4695
0
                        }
4696
57.4k
                        else
4697
57.4k
                        {
4698
57.4k
                            if (JSON_UNLIKELY(not sax->number_float(res, m_lexer.get_string())))
4699
57.4k
                            {
4700
0
                                return false;
4701
0
                            }
4702
57.4k
                            break;
4703
57.4k
                        }
4704
0
                    }
4705
0
4706
0
                    case token_type::literal_false:
4707
0
                    {
4708
0
                        if (JSON_UNLIKELY(not sax->boolean(false)))
4709
0
                        {
4710
0
                            return false;
4711
0
                        }
4712
0
                        break;
4713
0
                    }
4714
0
4715
402
                    case token_type::literal_null:
4716
402
                    {
4717
402
                        if (JSON_UNLIKELY(not sax->null()))
4718
402
                        {
4719
0
                            return false;
4720
0
                        }
4721
402
                        break;
4722
402
                    }
4723
402
4724
602
                    case token_type::literal_true:
4725
602
                    {
4726
602
                        if (JSON_UNLIKELY(not sax->boolean(true)))
4727
602
                        {
4728
0
                            return false;
4729
0
                        }
4730
602
                        break;
4731
602
                    }
4732
602
4733
9.18k
                    case token_type::value_integer:
4734
9.18k
                    {
4735
9.18k
                        if (JSON_UNLIKELY(not sax->number_integer(m_lexer.get_number_integer())))
4736
9.18k
                        {
4737
0
                            return false;
4738
0
                        }
4739
9.18k
                        break;
4740
9.18k
                    }
4741
9.18k
4742
61.8k
                    case token_type::value_string:
4743
61.8k
                    {
4744
61.8k
                        if (JSON_UNLIKELY(not sax->string(m_lexer.get_string())))
4745
61.8k
                        {
4746
0
                            return false;
4747
0
                        }
4748
61.8k
                        break;
4749
61.8k
                    }
4750
61.8k
4751
77.0k
                    case token_type::value_unsigned:
4752
77.0k
                    {
4753
77.0k
                        if (JSON_UNLIKELY(not sax->number_unsigned(m_lexer.get_number_unsigned())))
4754
77.0k
                        {
4755
0
                            return false;
4756
0
                        }
4757
77.0k
                        break;
4758
77.0k
                    }
4759
77.0k
4760
77.0k
                    case token_type::parse_error:
4761
0
                    {
4762
0
                        // using "uninitialized" to avoid "expected" message
4763
0
                        return sax->parse_error(m_lexer.get_position(),
4764
0
                                                m_lexer.get_token_string(),
4765
0
                                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized)));
4766
77.0k
                    }
4767
77.0k
4768
77.0k
                    default: // the last token was unexpected
4769
1
                    {
4770
1
                        return sax->parse_error(m_lexer.get_position(),
4771
1
                                                m_lexer.get_token_string(),
4772
1
                                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value)));
4773
51.2k
                    }
4774
51.2k
                }
4775
51.2k
            }
4776
51.2k
            else
4777
51.2k
            {
4778
51.2k
                skip_to_state_evaluation = false;
4779
51.2k
            }
4780
309k
4781
309k
            // we reached this line after we successfully parsed a value
4782
309k
            if (states.empty())
4783
834
            {
4784
834
                // empty stack: we reached the end of the hieararchy: done
4785
834
                return true;
4786
834
            }
4787
257k
            else
4788
257k
            {
4789
257k
                if (states.back())  // array
4790
9.57k
                {
4791
9.57k
                    // comma -> next value
4792
9.57k
                    if (get_token() == token_type::value_separator)
4793
9.17k
                    {
4794
9.17k
                        // parse a new value
4795
9.17k
                        get_token();
4796
9.17k
                        continue;
4797
9.17k
                    }
4798
402
4799
402
                    // closing ]
4800
402
                    if (JSON_LIKELY(last_token == token_type::end_array))
4801
402
                    {
4802
402
                        if (JSON_UNLIKELY(not sax->end_array()))
4803
402
                        {
4804
0
                            return false;
4805
0
                        }
4806
402
4807
402
                        // We are done with this array. Before we can parse a
4808
402
                        // new value, we need to evaluate the new state first.
4809
402
                        // By setting skip_to_state_evaluation to false, we
4810
402
                        // are effectively jumping to the beginning of this if.
4811
402
                        assert(not states.empty());
4812
402
                        states.pop_back();
4813
402
                        skip_to_state_evaluation = true;
4814
402
                        continue;
4815
402
                    }
4816
0
                    else
4817
0
                    {
4818
0
                        return sax->parse_error(m_lexer.get_position(),
4819
0
                                                m_lexer.get_token_string(),
4820
0
                                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array)));
4821
0
                    }
4822
247k
                }
4823
247k
                else  // object
4824
247k
                {
4825
247k
                    // comma -> next value
4826
247k
                    if (get_token() == token_type::value_separator)
4827
196k
                    {
4828
196k
                        // parse key
4829
196k
                        if (JSON_UNLIKELY(get_token() != token_type::value_string))
4830
196k
                        {
4831
0
                            return sax->parse_error(m_lexer.get_position(),
4832
0
                                                    m_lexer.get_token_string(),
4833
0
                                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string)));
4834
0
                        }
4835
196k
                        else
4836
196k
                        {
4837
196k
                            if (JSON_UNLIKELY(not sax->key(m_lexer.get_string())))
4838
196k
                            {
4839
0
                                return false;
4840
0
                            }
4841
196k
                        }
4842
196k
4843
196k
                        // parse separator (:)
4844
196k
                        if (JSON_UNLIKELY(get_token() != token_type::name_separator))
4845
196k
                        {
4846
0
                            return sax->parse_error(m_lexer.get_position(),
4847
0
                                                    m_lexer.get_token_string(),
4848
0
                                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator)));
4849
0
                        }
4850
196k
4851
196k
                        // parse values
4852
196k
                        get_token();
4853
196k
                        continue;
4854
196k
                    }
4855
50.8k
4856
50.8k
                    // closing }
4857
50.8k
                    if (JSON_LIKELY(last_token == token_type::end_object))
4858
50.8k
                    {
4859
50.8k
                        if (JSON_UNLIKELY(not sax->end_object()))
4860
50.8k
                        {
4861
0
                            return false;
4862
0
                        }
4863
50.8k
4864
50.8k
                        // We are done with this object. Before we can parse a
4865
50.8k
                        // new value, we need to evaluate the new state first.
4866
50.8k
                        // By setting skip_to_state_evaluation to false, we
4867
50.8k
                        // are effectively jumping to the beginning of this if.
4868
50.8k
                        assert(not states.empty());
4869
50.8k
                        states.pop_back();
4870
50.8k
                        skip_to_state_evaluation = true;
4871
50.8k
                        continue;
4872
50.8k
                    }
4873
0
                    else
4874
0
                    {
4875
0
                        return sax->parse_error(m_lexer.get_position(),
4876
0
                                                m_lexer.get_token_string(),
4877
0
                                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object)));
4878
0
                    }
4879
50.8k
                }
4880
257k
            }
4881
257k
        }
4882
835
    }
4883
4884
    /// get next token from lexer
4885
    token_type get_token()
4886
1.01M
    {
4887
1.01M
        return (last_token = m_lexer.scan());
4888
1.01M
    }
4889
4890
    std::string exception_message(const token_type expected)
4891
1
    {
4892
1
        std::string error_msg = "syntax error - ";
4893
1
        if (last_token == token_type::parse_error)
4894
0
        {
4895
0
            error_msg += std::string(m_lexer.get_error_message()) + "; last read: '" +
4896
0
                         m_lexer.get_token_string() + "'";
4897
0
        }
4898
1
        else
4899
1
        {
4900
1
            error_msg += "unexpected " + std::string(lexer_t::token_type_name(last_token));
4901
1
        }
4902
1
4903
1
        if (expected != token_type::uninitialized)
4904
1
        {
4905
1
            error_msg += "; expected " + std::string(lexer_t::token_type_name(expected));
4906
1
        }
4907
1
4908
1
        return error_msg;
4909
1
    }
4910
4911
  private:
4912
    /// callback function
4913
    const parser_callback_t callback = nullptr;
4914
    /// the type of the last read token
4915
    token_type last_token = token_type::uninitialized;
4916
    /// the lexer
4917
    lexer_t m_lexer;
4918
    /// whether to throw exceptions in case of errors
4919
    const bool allow_exceptions = true;
4920
};
4921
}
4922
}
4923
4924
// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
4925
4926
4927
#include <cstddef> // ptrdiff_t
4928
#include <limits>  // numeric_limits
4929
4930
namespace nlohmann
4931
{
4932
namespace detail
4933
{
4934
/*
4935
@brief an iterator for primitive JSON types
4936
4937
This class models an iterator for primitive JSON types (boolean, number,
4938
string). It's only purpose is to allow the iterator/const_iterator classes
4939
to "iterate" over primitive values. Internally, the iterator is modeled by
4940
a `difference_type` variable. Value begin_value (`0`) models the begin,
4941
end_value (`1`) models past the end.
4942
*/
4943
class primitive_iterator_t
4944
{
4945
  private:
4946
    using difference_type = std::ptrdiff_t;
4947
    static constexpr difference_type begin_value = 0;
4948
    static constexpr difference_type end_value = begin_value + 1;
4949
4950
    /// iterator as signed integer type
4951
    difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
4952
4953
  public:
4954
    constexpr difference_type get_value() const noexcept
4955
0
    {
4956
0
        return m_it;
4957
0
    }
4958
4959
    /// set iterator to a defined beginning
4960
    void set_begin() noexcept
4961
0
    {
4962
0
        m_it = begin_value;
4963
0
    }
4964
4965
    /// set iterator to a defined past the end
4966
    void set_end() noexcept
4967
2
    {
4968
2
        m_it = end_value;
4969
2
    }
4970
4971
    /// return whether the iterator can be dereferenced
4972
    constexpr bool is_begin() const noexcept
4973
0
    {
4974
0
        return m_it == begin_value;
4975
0
    }
4976
4977
    /// return whether the iterator is at end
4978
    constexpr bool is_end() const noexcept
4979
0
    {
4980
0
        return m_it == end_value;
4981
0
    }
4982
4983
    friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
4984
1
    {
4985
1
        return lhs.m_it == rhs.m_it;
4986
1
    }
4987
4988
    friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
4989
    {
4990
        return lhs.m_it < rhs.m_it;
4991
    }
4992
4993
    primitive_iterator_t operator+(difference_type n) noexcept
4994
0
    {
4995
0
        auto result = *this;
4996
0
        result += n;
4997
0
        return result;
4998
0
    }
4999
5000
    friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
5001
    {
5002
        return lhs.m_it - rhs.m_it;
5003
    }
5004
5005
    primitive_iterator_t& operator++() noexcept
5006
0
    {
5007
0
        ++m_it;
5008
0
        return *this;
5009
0
    }
5010
5011
    primitive_iterator_t const operator++(int) noexcept
5012
0
    {
5013
0
        auto result = *this;
5014
0
        ++m_it;
5015
0
        return result;
5016
0
    }
5017
5018
    primitive_iterator_t& operator--() noexcept
5019
0
    {
5020
0
        --m_it;
5021
0
        return *this;
5022
0
    }
5023
5024
    primitive_iterator_t const operator--(int) noexcept
5025
0
    {
5026
0
        auto result = *this;
5027
0
        --m_it;
5028
0
        return result;
5029
0
    }
5030
5031
    primitive_iterator_t& operator+=(difference_type n) noexcept
5032
0
    {
5033
0
        m_it += n;
5034
0
        return *this;
5035
0
    }
5036
5037
    primitive_iterator_t& operator-=(difference_type n) noexcept
5038
0
    {
5039
0
        m_it -= n;
5040
0
        return *this;
5041
0
    }
5042
};
5043
}
5044
}
5045
5046
// #include <nlohmann/detail/iterators/internal_iterator.hpp>
5047
5048
5049
// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
5050
5051
5052
namespace nlohmann
5053
{
5054
namespace detail
5055
{
5056
/*!
5057
@brief an iterator value
5058
5059
@note This structure could easily be a union, but MSVC currently does not allow
5060
unions members with complex constructors, see https://github.com/nlohmann/json/pull/105.
5061
*/
5062
template<typename BasicJsonType> struct internal_iterator
5063
{
5064
    /// iterator for JSON objects
5065
    typename BasicJsonType::object_t::iterator object_iterator {};
5066
    /// iterator for JSON arrays
5067
    typename BasicJsonType::array_t::iterator array_iterator {};
5068
    /// generic iterator for all other types
5069
    primitive_iterator_t primitive_iterator {};
5070
};
5071
}
5072
}
5073
5074
// #include <nlohmann/detail/iterators/iter_impl.hpp>
5075
5076
5077
#include <ciso646> // not
5078
#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
5079
#include <type_traits> // conditional, is_const, remove_const
5080
5081
// #include <nlohmann/detail/exceptions.hpp>
5082
5083
// #include <nlohmann/detail/iterators/internal_iterator.hpp>
5084
5085
// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
5086
5087
// #include <nlohmann/detail/macro_scope.hpp>
5088
5089
// #include <nlohmann/detail/meta/cpp_future.hpp>
5090
5091
// #include <nlohmann/detail/value_t.hpp>
5092
5093
5094
namespace nlohmann
5095
{
5096
namespace detail
5097
{
5098
// forward declare, to be able to friend it later on
5099
template<typename IteratorType> class iteration_proxy;
5100
5101
/*!
5102
@brief a template for a bidirectional iterator for the @ref basic_json class
5103
5104
This class implements a both iterators (iterator and const_iterator) for the
5105
@ref basic_json class.
5106
5107
@note An iterator is called *initialized* when a pointer to a JSON value has
5108
      been set (e.g., by a constructor or a copy assignment). If the iterator is
5109
      default-constructed, it is *uninitialized* and most methods are undefined.
5110
      **The library uses assertions to detect calls on uninitialized iterators.**
5111
5112
@requirement The class satisfies the following concept requirements:
5113
-
5114
[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
5115
  The iterator that can be moved can be moved in both directions (i.e.
5116
  incremented and decremented).
5117
5118
@since version 1.0.0, simplified in version 2.0.9, change to bidirectional
5119
       iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593)
5120
*/
5121
template<typename BasicJsonType>
5122
class iter_impl
5123
{
5124
    /// allow basic_json to access private members
5125
    friend iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
5126
    friend BasicJsonType;
5127
    friend iteration_proxy<iter_impl>;
5128
5129
    using object_t = typename BasicJsonType::object_t;
5130
    using array_t = typename BasicJsonType::array_t;
5131
    // make sure BasicJsonType is basic_json or const basic_json
5132
    static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value,
5133
                  "iter_impl only accepts (const) basic_json");
5134
5135
  public:
5136
5137
    /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
5138
    /// The C++ Standard has never required user-defined iterators to derive from std::iterator.
5139
    /// A user-defined iterator should provide publicly accessible typedefs named
5140
    /// iterator_category, value_type, difference_type, pointer, and reference.
5141
    /// Note that value_type is required to be non-const, even for constant iterators.
5142
    using iterator_category = std::bidirectional_iterator_tag;
5143
5144
    /// the type of the values when the iterator is dereferenced
5145
    using value_type = typename BasicJsonType::value_type;
5146
    /// a type to represent differences between iterators
5147
    using difference_type = typename BasicJsonType::difference_type;
5148
    /// defines a pointer to the type iterated over (value_type)
5149
    using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
5150
          typename BasicJsonType::const_pointer,
5151
          typename BasicJsonType::pointer>::type;
5152
    /// defines a reference to the type iterated over (value_type)
5153
    using reference =
5154
        typename std::conditional<std::is_const<BasicJsonType>::value,
5155
        typename BasicJsonType::const_reference,
5156
        typename BasicJsonType::reference>::type;
5157
5158
    /// default constructor
5159
    iter_impl() = default;
5160
5161
    /*!
5162
    @brief constructor for a given JSON instance
5163
    @param[in] object  pointer to a JSON object for this iterator
5164
    @pre object != nullptr
5165
    @post The iterator is initialized; i.e. `m_object != nullptr`.
5166
    */
5167
    explicit iter_impl(pointer object) noexcept : m_object(object)
5168
2.57k
    {
5169
2.57k
        assert(m_object != nullptr);
5170
2.57k
5171
2.57k
        switch (m_object->m_type)
5172
2.57k
        {
5173
2.57k
            case value_t::object:
5174
2.55k
            {
5175
2.55k
                m_it.object_iterator = typename object_t::iterator();
5176
2.55k
                break;
5177
2.57k
            }
5178
2.57k
5179
2.57k
            case value_t::array:
5180
16
            {
5181
16
                m_it.array_iterator = typename array_t::iterator();
5182
16
                break;
5183
2.57k
            }
5184
2.57k
5185
2.57k
            default:
5186
2
            {
5187
2
                m_it.primitive_iterator = primitive_iterator_t();
5188
2
                break;
5189
2.57k
            }
5190
2.57k
        }
5191
2.57k
    }
5192
5193
    /*!
5194
    @note The conventional copy constructor and copy assignment are implicitly
5195
          defined. Combined with the following converting constructor and
5196
          assignment, they support: (1) copy from iterator to iterator, (2)
5197
          copy from const iterator to const iterator, and (3) conversion from
5198
          iterator to const iterator. However conversion from const iterator
5199
          to iterator is not defined.
5200
    */
5201
5202
    /*!
5203
    @brief converting constructor
5204
    @param[in] other  non-const iterator to copy from
5205
    @note It is not checked whether @a other is initialized.
5206
    */
5207
    iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
5208
0
        : m_object(other.m_object), m_it(other.m_it) {}
5209
5210
    /*!
5211
    @brief converting assignment
5212
    @param[in,out] other  non-const iterator to copy from
5213
    @return const/non-const iterator
5214
    @note It is not checked whether @a other is initialized.
5215
    */
5216
    iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
5217
    {
5218
        m_object = other.m_object;
5219
        m_it = other.m_it;
5220
        return *this;
5221
    }
5222
5223
  private:
5224
    /*!
5225
    @brief set the iterator to the first value
5226
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5227
    */
5228
    void set_begin() noexcept
5229
590
    {
5230
590
        assert(m_object != nullptr);
5231
590
5232
590
        switch (m_object->m_type)
5233
590
        {
5234
590
            case value_t::object:
5235
582
            {
5236
582
                m_it.object_iterator = m_object->m_value.object->begin();
5237
582
                break;
5238
590
            }
5239
590
5240
590
            case value_t::array:
5241
8
            {
5242
8
                m_it.array_iterator = m_object->m_value.array->begin();
5243
8
                break;
5244
590
            }
5245
590
5246
590
            case value_t::null:
5247
0
            {
5248
0
                // set to end so begin()==end() is true: null is empty
5249
0
                m_it.primitive_iterator.set_end();
5250
0
                break;
5251
590
            }
5252
590
5253
590
            default:
5254
0
            {
5255
0
                m_it.primitive_iterator.set_begin();
5256
0
                break;
5257
590
            }
5258
590
        }
5259
590
    }
5260
5261
    /*!
5262
    @brief set the iterator past the last value
5263
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5264
    */
5265
    void set_end() noexcept
5266
1.98k
    {
5267
1.98k
        assert(m_object != nullptr);
5268
1.98k
5269
1.98k
        switch (m_object->m_type)
5270
1.98k
        {
5271
1.98k
            case value_t::object:
5272
1.97k
            {
5273
1.97k
                m_it.object_iterator = m_object->m_value.object->end();
5274
1.97k
                break;
5275
1.98k
            }
5276
1.98k
5277
1.98k
            case value_t::array:
5278
8
            {
5279
8
                m_it.array_iterator = m_object->m_value.array->end();
5280
8
                break;
5281
1.98k
            }
5282
1.98k
5283
1.98k
            default:
5284
2
            {
5285
2
                m_it.primitive_iterator.set_end();
5286
2
                break;
5287
1.98k
            }
5288
1.98k
        }
5289
1.98k
    }
5290
5291
  public:
5292
    /*!
5293
    @brief return a reference to the value pointed to by the iterator
5294
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5295
    */
5296
    reference operator*() const
5297
1.51k
    {
5298
1.51k
        assert(m_object != nullptr);
5299
1.51k
5300
1.51k
        switch (m_object->m_type)
5301
1.51k
        {
5302
1.51k
            case value_t::object:
5303
1.36k
            {
5304
1.36k
                assert(m_it.object_iterator != m_object->m_value.object->end());
5305
1.36k
                return m_it.object_iterator->second;
5306
1.51k
            }
5307
1.51k
5308
1.51k
            case value_t::array:
5309
146
            {
5310
146
                assert(m_it.array_iterator != m_object->m_value.array->end());
5311
146
                return *m_it.array_iterator;
5312
1.51k
            }
5313
1.51k
5314
1.51k
            case value_t::null:
5315
0
                JSON_THROW(invalid_iterator::create(214, "cannot get value"));
5316
1.51k
5317
1.51k
            default:
5318
0
            {
5319
0
                if (JSON_LIKELY(m_it.primitive_iterator.is_begin()))
5320
0
                {
5321
0
                    return *m_object;
5322
0
                }
5323
0
5324
0
                JSON_THROW(invalid_iterator::create(214, "cannot get value"));
5325
0
            }
5326
0
        }
5327
0
    }
5328
5329
    /*!
5330
    @brief dereference the iterator
5331
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5332
    */
5333
    pointer operator->() const
5334
0
    {
5335
0
        assert(m_object != nullptr);
5336
0
5337
0
        switch (m_object->m_type)
5338
0
        {
5339
0
            case value_t::object:
5340
0
            {
5341
0
                assert(m_it.object_iterator != m_object->m_value.object->end());
5342
0
                return &(m_it.object_iterator->second);
5343
0
            }
5344
0
5345
0
            case value_t::array:
5346
0
            {
5347
0
                assert(m_it.array_iterator != m_object->m_value.array->end());
5348
0
                return &*m_it.array_iterator;
5349
0
            }
5350
0
5351
0
            default:
5352
0
            {
5353
0
                if (JSON_LIKELY(m_it.primitive_iterator.is_begin()))
5354
0
                {
5355
0
                    return m_object;
5356
0
                }
5357
0
5358
0
                JSON_THROW(invalid_iterator::create(214, "cannot get value"));
5359
0
            }
5360
0
        }
5361
0
    }
5362
5363
    /*!
5364
    @brief post-increment (it++)
5365
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5366
    */
5367
    iter_impl const operator++(int)
5368
    {
5369
        auto result = *this;
5370
        ++(*this);
5371
        return result;
5372
    }
5373
5374
    /*!
5375
    @brief pre-increment (++it)
5376
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5377
    */
5378
    iter_impl& operator++()
5379
1.50k
    {
5380
1.50k
        assert(m_object != nullptr);
5381
1.50k
5382
1.50k
        switch (m_object->m_type)
5383
1.50k
        {
5384
1.50k
            case value_t::object:
5385
1.36k
            {
5386
1.36k
                std::advance(m_it.object_iterator, 1);
5387
1.36k
                break;
5388
1.50k
            }
5389
1.50k
5390
1.50k
            case value_t::array:
5391
146
            {
5392
146
                std::advance(m_it.array_iterator, 1);
5393
146
                break;
5394
1.50k
            }
5395
1.50k
5396
1.50k
            default:
5397
0
            {
5398
0
                ++m_it.primitive_iterator;
5399
0
                break;
5400
1.50k
            }
5401
1.50k
        }
5402
1.50k
5403
1.50k
        return *this;
5404
1.50k
    }
5405
5406
    /*!
5407
    @brief post-decrement (it--)
5408
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5409
    */
5410
    iter_impl const operator--(int)
5411
    {
5412
        auto result = *this;
5413
        --(*this);
5414
        return result;
5415
    }
5416
5417
    /*!
5418
    @brief pre-decrement (--it)
5419
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5420
    */
5421
    iter_impl& operator--()
5422
    {
5423
        assert(m_object != nullptr);
5424
5425
        switch (m_object->m_type)
5426
        {
5427
            case value_t::object:
5428
            {
5429
                std::advance(m_it.object_iterator, -1);
5430
                break;
5431
            }
5432
5433
            case value_t::array:
5434
            {
5435
                std::advance(m_it.array_iterator, -1);
5436
                break;
5437
            }
5438
5439
            default:
5440
            {
5441
                --m_it.primitive_iterator;
5442
                break;
5443
            }
5444
        }
5445
5446
        return *this;
5447
    }
5448
5449
    /*!
5450
    @brief  comparison: equal
5451
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5452
    */
5453
    bool operator==(const iter_impl& other) const
5454
2.11k
    {
5455
2.11k
        // if objects are not the same, the comparison is undefined
5456
2.11k
        if (JSON_UNLIKELY(m_object != other.m_object))
5457
2.11k
        {
5458
0
            JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
5459
0
        }
5460
2.11k
5461
2.11k
        assert(m_object != nullptr);
5462
2.11k
5463
2.11k
        switch (m_object->m_type)
5464
2.11k
        {
5465
2.11k
            case value_t::object:
5466
1.95k
                return (m_it.object_iterator == other.m_it.object_iterator);
5467
2.11k
5468
2.11k
            case value_t::array:
5469
154
                return (m_it.array_iterator == other.m_it.array_iterator);
5470
2.11k
5471
2.11k
            default:
5472
1
                return (m_it.primitive_iterator == other.m_it.primitive_iterator);
5473
0
        }
5474
0
    }
5475
5476
    /*!
5477
    @brief  comparison: not equal
5478
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5479
    */
5480
    bool operator!=(const iter_impl& other) const
5481
2.11k
    {
5482
2.11k
        return not operator==(other);
5483
2.11k
    }
5484
5485
    /*!
5486
    @brief  comparison: smaller
5487
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5488
    */
5489
    bool operator<(const iter_impl& other) const
5490
    {
5491
        // if objects are not the same, the comparison is undefined
5492
        if (JSON_UNLIKELY(m_object != other.m_object))
5493
        {
5494
            JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
5495
        }
5496
5497
        assert(m_object != nullptr);
5498
5499
        switch (m_object->m_type)
5500
        {
5501
            case value_t::object:
5502
                JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators"));
5503
5504
            case value_t::array:
5505
                return (m_it.array_iterator < other.m_it.array_iterator);
5506
5507
            default:
5508
                return (m_it.primitive_iterator < other.m_it.primitive_iterator);
5509
        }
5510
    }
5511
5512
    /*!
5513
    @brief  comparison: less than or equal
5514
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5515
    */
5516
    bool operator<=(const iter_impl& other) const
5517
    {
5518
        return not other.operator < (*this);
5519
    }
5520
5521
    /*!
5522
    @brief  comparison: greater than
5523
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5524
    */
5525
    bool operator>(const iter_impl& other) const
5526
    {
5527
        return not operator<=(other);
5528
    }
5529
5530
    /*!
5531
    @brief  comparison: greater than or equal
5532
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5533
    */
5534
    bool operator>=(const iter_impl& other) const
5535
    {
5536
        return not operator<(other);
5537
    }
5538
5539
    /*!
5540
    @brief  add to iterator
5541
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5542
    */
5543
    iter_impl& operator+=(difference_type i)
5544
    {
5545
        assert(m_object != nullptr);
5546
5547
        switch (m_object->m_type)
5548
        {
5549
            case value_t::object:
5550
                JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
5551
5552
            case value_t::array:
5553
            {
5554
                std::advance(m_it.array_iterator, i);
5555
                break;
5556
            }
5557
5558
            default:
5559
            {
5560
                m_it.primitive_iterator += i;
5561
                break;
5562
            }
5563
        }
5564
5565
        return *this;
5566
    }
5567
5568
    /*!
5569
    @brief  subtract from iterator
5570
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5571
    */
5572
    iter_impl& operator-=(difference_type i)
5573
    {
5574
        return operator+=(-i);
5575
    }
5576
5577
    /*!
5578
    @brief  add to iterator
5579
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5580
    */
5581
    iter_impl operator+(difference_type i) const
5582
    {
5583
        auto result = *this;
5584
        result += i;
5585
        return result;
5586
    }
5587
5588
    /*!
5589
    @brief  addition of distance and iterator
5590
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5591
    */
5592
    friend iter_impl operator+(difference_type i, const iter_impl& it)
5593
    {
5594
        auto result = it;
5595
        result += i;
5596
        return result;
5597
    }
5598
5599
    /*!
5600
    @brief  subtract from iterator
5601
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5602
    */
5603
    iter_impl operator-(difference_type i) const
5604
    {
5605
        auto result = *this;
5606
        result -= i;
5607
        return result;
5608
    }
5609
5610
    /*!
5611
    @brief  return difference
5612
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5613
    */
5614
    difference_type operator-(const iter_impl& other) const
5615
    {
5616
        assert(m_object != nullptr);
5617
5618
        switch (m_object->m_type)
5619
        {
5620
            case value_t::object:
5621
                JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
5622
5623
            case value_t::array:
5624
                return m_it.array_iterator - other.m_it.array_iterator;
5625
5626
            default:
5627
                return m_it.primitive_iterator - other.m_it.primitive_iterator;
5628
        }
5629
    }
5630
5631
    /*!
5632
    @brief  access to successor
5633
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5634
    */
5635
    reference operator[](difference_type n) const
5636
    {
5637
        assert(m_object != nullptr);
5638
5639
        switch (m_object->m_type)
5640
        {
5641
            case value_t::object:
5642
                JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators"));
5643
5644
            case value_t::array:
5645
                return *std::next(m_it.array_iterator, n);
5646
5647
            case value_t::null:
5648
                JSON_THROW(invalid_iterator::create(214, "cannot get value"));
5649
5650
            default:
5651
            {
5652
                if (JSON_LIKELY(m_it.primitive_iterator.get_value() == -n))
5653
                {
5654
                    return *m_object;
5655
                }
5656
5657
                JSON_THROW(invalid_iterator::create(214, "cannot get value"));
5658
            }
5659
        }
5660
    }
5661
5662
    /*!
5663
    @brief  return the key of an object iterator
5664
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5665
    */
5666
    const typename object_t::key_type& key() const
5667
0
    {
5668
0
        assert(m_object != nullptr);
5669
0
5670
0
        if (JSON_LIKELY(m_object->is_object()))
5671
0
        {
5672
0
            return m_it.object_iterator->first;
5673
0
        }
5674
0
5675
0
        JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators"));
5676
0
    }
5677
5678
    /*!
5679
    @brief  return the value of an iterator
5680
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5681
    */
5682
    reference value() const
5683
1.36k
    {
5684
1.36k
        return operator*();
5685
1.36k
    }
5686
5687
  private:
5688
    /// associated JSON instance
5689
    pointer m_object = nullptr;
5690
    /// the actual iterator of the associated instance
5691
    internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it;
5692
};
5693
}
5694
}
5695
5696
// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
5697
5698
// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
5699
5700
5701
#include <cstddef> // ptrdiff_t
5702
#include <iterator> // reverse_iterator
5703
#include <utility> // declval
5704
5705
namespace nlohmann
5706
{
5707
namespace detail
5708
{
5709
//////////////////////
5710
// reverse_iterator //
5711
//////////////////////
5712
5713
/*!
5714
@brief a template for a reverse iterator class
5715
5716
@tparam Base the base iterator type to reverse. Valid types are @ref
5717
iterator (to create @ref reverse_iterator) and @ref const_iterator (to
5718
create @ref const_reverse_iterator).
5719
5720
@requirement The class satisfies the following concept requirements:
5721
-
5722
[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
5723
  The iterator that can be moved can be moved in both directions (i.e.
5724
  incremented and decremented).
5725
- [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator):
5726
  It is possible to write to the pointed-to element (only if @a Base is
5727
  @ref iterator).
5728
5729
@since version 1.0.0
5730
*/
5731
template<typename Base>
5732
class json_reverse_iterator : public std::reverse_iterator<Base>
5733
{
5734
  public:
5735
    using difference_type = std::ptrdiff_t;
5736
    /// shortcut to the reverse iterator adapter
5737
    using base_iterator = std::reverse_iterator<Base>;
5738
    /// the reference type for the pointed-to element
5739
    using reference = typename Base::reference;
5740
5741
    /// create reverse iterator from iterator
5742
    explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
5743
        : base_iterator(it) {}
5744
5745
    /// create reverse iterator from base class
5746
    explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
5747
5748
    /// post-increment (it++)
5749
    json_reverse_iterator const operator++(int)
5750
    {
5751
        return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
5752
    }
5753
5754
    /// pre-increment (++it)
5755
    json_reverse_iterator& operator++()
5756
    {
5757
        return static_cast<json_reverse_iterator&>(base_iterator::operator++());
5758
    }
5759
5760
    /// post-decrement (it--)
5761
    json_reverse_iterator const operator--(int)
5762
    {
5763
        return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
5764
    }
5765
5766
    /// pre-decrement (--it)
5767
    json_reverse_iterator& operator--()
5768
    {
5769
        return static_cast<json_reverse_iterator&>(base_iterator::operator--());
5770
    }
5771
5772
    /// add to iterator
5773
    json_reverse_iterator& operator+=(difference_type i)
5774
    {
5775
        return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
5776
    }
5777
5778
    /// add to iterator
5779
    json_reverse_iterator operator+(difference_type i) const
5780
    {
5781
        return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
5782
    }
5783
5784
    /// subtract from iterator
5785
    json_reverse_iterator operator-(difference_type i) const
5786
    {
5787
        return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
5788
    }
5789
5790
    /// return difference
5791
    difference_type operator-(const json_reverse_iterator& other) const
5792
    {
5793
        return base_iterator(*this) - base_iterator(other);
5794
    }
5795
5796
    /// access to successor
5797
    reference operator[](difference_type n) const
5798
    {
5799
        return *(this->operator+(n));
5800
    }
5801
5802
    /// return the key of an object iterator
5803
    auto key() const -> decltype(std::declval<Base>().key())
5804
    {
5805
        auto it = --this->base();
5806
        return it.key();
5807
    }
5808
5809
    /// return the value of an iterator
5810
    reference value() const
5811
    {
5812
        auto it = --this->base();
5813
        return it.operator * ();
5814
    }
5815
};
5816
}
5817
}
5818
5819
// #include <nlohmann/detail/output/output_adapters.hpp>
5820
5821
5822
#include <algorithm> // copy
5823
#include <cstddef> // size_t
5824
#include <ios> // streamsize
5825
#include <iterator> // back_inserter
5826
#include <memory> // shared_ptr, make_shared
5827
#include <ostream> // basic_ostream
5828
#include <string> // basic_string
5829
#include <vector> // vector
5830
5831
namespace nlohmann
5832
{
5833
namespace detail
5834
{
5835
/// abstract output adapter interface
5836
template<typename CharType> struct output_adapter_protocol
5837
{
5838
    virtual void write_character(CharType c) = 0;
5839
    virtual void write_characters(const CharType* s, std::size_t length) = 0;
5840
122
    virtual ~output_adapter_protocol() = default;
5841
};
5842
5843
/// a type to simplify interfaces
5844
template<typename CharType>
5845
using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
5846
5847
/// output adapter for byte vectors
5848
template<typename CharType>
5849
class output_vector_adapter : public output_adapter_protocol<CharType>
5850
{
5851
  public:
5852
    explicit output_vector_adapter(std::vector<CharType>& vec) : v(vec) {}
5853
5854
    void write_character(CharType c) override
5855
    {
5856
        v.push_back(c);
5857
    }
5858
5859
    void write_characters(const CharType* s, std::size_t length) override
5860
    {
5861
        std::copy(s, s + length, std::back_inserter(v));
5862
    }
5863
5864
  private:
5865
    std::vector<CharType>& v;
5866
};
5867
5868
/// output adapter for output streams
5869
template<typename CharType>
5870
class output_stream_adapter : public output_adapter_protocol<CharType>
5871
{
5872
  public:
5873
105
    explicit output_stream_adapter(std::basic_ostream<CharType>& s) : stream(s) {}
5874
5875
    void write_character(CharType c) override
5876
7.48k
    {
5877
7.48k
        stream.put(c);
5878
7.48k
    }
5879
5880
    void write_characters(const CharType* s, std::size_t length) override
5881
10.3k
    {
5882
10.3k
        stream.write(s, static_cast<std::streamsize>(length));
5883
10.3k
    }
5884
5885
  private:
5886
    std::basic_ostream<CharType>& stream;
5887
};
5888
5889
/// output adapter for basic_string
5890
template<typename CharType, typename StringType = std::basic_string<CharType>>
5891
class output_string_adapter : public output_adapter_protocol<CharType>
5892
{
5893
  public:
5894
17
    explicit output_string_adapter(StringType& s) : str(s) {}
5895
5896
    void write_character(CharType c) override
5897
111
    {
5898
111
        str.push_back(c);
5899
111
    }
5900
5901
    void write_characters(const CharType* s, std::size_t length) override
5902
241
    {
5903
241
        str.append(s, length);
5904
241
    }
5905
5906
  private:
5907
    StringType& str;
5908
};
5909
5910
template<typename CharType, typename StringType = std::basic_string<CharType>>
5911
class output_adapter
5912
{
5913
  public:
5914
    output_adapter(std::vector<CharType>& vec)
5915
        : oa(std::make_shared<output_vector_adapter<CharType>>(vec)) {}
5916
5917
    output_adapter(std::basic_ostream<CharType>& s)
5918
105
        : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
5919
5920
    output_adapter(StringType& s)
5921
17
        : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
5922
5923
    operator output_adapter_t<CharType>()
5924
122
    {
5925
122
        return oa;
5926
122
    }
5927
5928
  private:
5929
    output_adapter_t<CharType> oa = nullptr;
5930
};
5931
}
5932
}
5933
5934
// #include <nlohmann/detail/input/binary_reader.hpp>
5935
5936
5937
#include <algorithm> // generate_n
5938
#include <array> // array
5939
#include <cassert> // assert
5940
#include <cmath> // ldexp
5941
#include <cstddef> // size_t
5942
#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
5943
#include <cstdio> // snprintf
5944
#include <cstring> // memcpy
5945
#include <iterator> // back_inserter
5946
#include <limits> // numeric_limits
5947
#include <string> // char_traits, string
5948
#include <utility> // make_pair, move
5949
5950
// #include <nlohmann/detail/input/input_adapters.hpp>
5951
5952
// #include <nlohmann/detail/input/json_sax.hpp>
5953
5954
// #include <nlohmann/detail/exceptions.hpp>
5955
5956
// #include <nlohmann/detail/macro_scope.hpp>
5957
5958
// #include <nlohmann/detail/meta/is_sax.hpp>
5959
5960
// #include <nlohmann/detail/value_t.hpp>
5961
5962
5963
namespace nlohmann
5964
{
5965
namespace detail
5966
{
5967
///////////////////
5968
// binary reader //
5969
///////////////////
5970
5971
/*!
5972
@brief deserialization of CBOR, MessagePack, and UBJSON values
5973
*/
5974
template<typename BasicJsonType, typename SAX = json_sax_dom_parser<BasicJsonType>>
5975
class binary_reader
5976
{
5977
    using number_integer_t = typename BasicJsonType::number_integer_t;
5978
    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5979
    using number_float_t = typename BasicJsonType::number_float_t;
5980
    using string_t = typename BasicJsonType::string_t;
5981
    using json_sax_t = SAX;
5982
5983
  public:
5984
    /*!
5985
    @brief create a binary reader
5986
5987
    @param[in] adapter  input adapter to read from
5988
    */
5989
    explicit binary_reader(input_adapter_t adapter) : ia(std::move(adapter))
5990
    {
5991
        (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
5992
        assert(ia);
5993
    }
5994
5995
    /*!
5996
    @param[in] format  the binary format to parse
5997
    @param[in] sax_    a SAX event processor
5998
    @param[in] strict  whether to expect the input to be consumed completed
5999
6000
    @return
6001
    */
6002
    bool sax_parse(const input_format_t format,
6003
                   json_sax_t* sax_,
6004
                   const bool strict = true)
6005
    {
6006
        sax = sax_;
6007
        bool result = false;
6008
6009
        switch (format)
6010
        {
6011
            case input_format_t::cbor:
6012
                result = parse_cbor_internal();
6013
                break;
6014
6015
            case input_format_t::msgpack:
6016
                result = parse_msgpack_internal();
6017
                break;
6018
6019
            case input_format_t::ubjson:
6020
                result = parse_ubjson_internal();
6021
                break;
6022
6023
            // LCOV_EXCL_START
6024
            default:
6025
                assert(false);
6026
                // LCOV_EXCL_STOP
6027
        }
6028
6029
        // strict mode: next byte must be EOF
6030
        if (result and strict)
6031
        {
6032
            if (format == input_format_t::ubjson)
6033
            {
6034
                get_ignore_noop();
6035
            }
6036
            else
6037
            {
6038
                get();
6039
            }
6040
6041
            if (JSON_UNLIKELY(current != std::char_traits<char>::eof()))
6042
            {
6043
                return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read, "expected end of input"));
6044
            }
6045
        }
6046
6047
        return result;
6048
    }
6049
6050
    /*!
6051
    @brief determine system byte order
6052
6053
    @return true if and only if system's byte order is little endian
6054
6055
    @note from http://stackoverflow.com/a/1001328/266378
6056
    */
6057
    static constexpr bool little_endianess(int num = 1) noexcept
6058
    {
6059
        return (*reinterpret_cast<char*>(&num) == 1);
6060
    }
6061
6062
  private:
6063
    /*!
6064
    @param[in] get_char  whether a new character should be retrieved from the
6065
                         input (true, default) or whether the last read
6066
                         character should be considered instead
6067
6068
    @return whether a valid CBOR value was passed to the SAX parser
6069
    */
6070
    bool parse_cbor_internal(const bool get_char = true)
6071
    {
6072
        switch (get_char ? get() : current)
6073
        {
6074
            // EOF
6075
            case std::char_traits<char>::eof():
6076
                return unexpect_eof();
6077
6078
            // Integer 0x00..0x17 (0..23)
6079
            case 0x00:
6080
            case 0x01:
6081
            case 0x02:
6082
            case 0x03:
6083
            case 0x04:
6084
            case 0x05:
6085
            case 0x06:
6086
            case 0x07:
6087
            case 0x08:
6088
            case 0x09:
6089
            case 0x0A:
6090
            case 0x0B:
6091
            case 0x0C:
6092
            case 0x0D:
6093
            case 0x0E:
6094
            case 0x0F:
6095
            case 0x10:
6096
            case 0x11:
6097
            case 0x12:
6098
            case 0x13:
6099
            case 0x14:
6100
            case 0x15:
6101
            case 0x16:
6102
            case 0x17:
6103
                return sax->number_unsigned(static_cast<number_unsigned_t>(current));
6104
6105
            case 0x18: // Unsigned integer (one-byte uint8_t follows)
6106
            {
6107
                uint8_t number;
6108
                return get_number(number) and sax->number_unsigned(number);
6109
            }
6110
6111
            case 0x19: // Unsigned integer (two-byte uint16_t follows)
6112
            {
6113
                uint16_t number;
6114
                return get_number(number) and sax->number_unsigned(number);
6115
            }
6116
6117
            case 0x1A: // Unsigned integer (four-byte uint32_t follows)
6118
            {
6119
                uint32_t number;
6120
                return get_number(number) and sax->number_unsigned(number);
6121
            }
6122
6123
            case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
6124
            {
6125
                uint64_t number;
6126
                return get_number(number) and sax->number_unsigned(number);
6127
            }
6128
6129
            // Negative integer -1-0x00..-1-0x17 (-1..-24)
6130
            case 0x20:
6131
            case 0x21:
6132
            case 0x22:
6133
            case 0x23:
6134
            case 0x24:
6135
            case 0x25:
6136
            case 0x26:
6137
            case 0x27:
6138
            case 0x28:
6139
            case 0x29:
6140
            case 0x2A:
6141
            case 0x2B:
6142
            case 0x2C:
6143
            case 0x2D:
6144
            case 0x2E:
6145
            case 0x2F:
6146
            case 0x30:
6147
            case 0x31:
6148
            case 0x32:
6149
            case 0x33:
6150
            case 0x34:
6151
            case 0x35:
6152
            case 0x36:
6153
            case 0x37:
6154
                return sax->number_integer(static_cast<int8_t>(0x20 - 1 - current));
6155
6156
            case 0x38: // Negative integer (one-byte uint8_t follows)
6157
            {
6158
                uint8_t number;
6159
                return get_number(number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
6160
            }
6161
6162
            case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
6163
            {
6164
                uint16_t number;
6165
                return get_number(number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
6166
            }
6167
6168
            case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
6169
            {
6170
                uint32_t number;
6171
                return get_number(number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
6172
            }
6173
6174
            case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
6175
            {
6176
                uint64_t number;
6177
                return get_number(number) and sax->number_integer(static_cast<number_integer_t>(-1)
6178
                        - static_cast<number_integer_t>(number));
6179
            }
6180
6181
            // UTF-8 string (0x00..0x17 bytes follow)
6182
            case 0x60:
6183
            case 0x61:
6184
            case 0x62:
6185
            case 0x63:
6186
            case 0x64:
6187
            case 0x65:
6188
            case 0x66:
6189
            case 0x67:
6190
            case 0x68:
6191
            case 0x69:
6192
            case 0x6A:
6193
            case 0x6B:
6194
            case 0x6C:
6195
            case 0x6D:
6196
            case 0x6E:
6197
            case 0x6F:
6198
            case 0x70:
6199
            case 0x71:
6200
            case 0x72:
6201
            case 0x73:
6202
            case 0x74:
6203
            case 0x75:
6204
            case 0x76:
6205
            case 0x77:
6206
            case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
6207
            case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
6208
            case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
6209
            case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
6210
            case 0x7F: // UTF-8 string (indefinite length)
6211
            {
6212
                string_t s;
6213
                return get_cbor_string(s) and sax->string(s);
6214
            }
6215
6216
            // array (0x00..0x17 data items follow)
6217
            case 0x80:
6218
            case 0x81:
6219
            case 0x82:
6220
            case 0x83:
6221
            case 0x84:
6222
            case 0x85:
6223
            case 0x86:
6224
            case 0x87:
6225
            case 0x88:
6226
            case 0x89:
6227
            case 0x8A:
6228
            case 0x8B:
6229
            case 0x8C:
6230
            case 0x8D:
6231
            case 0x8E:
6232
            case 0x8F:
6233
            case 0x90:
6234
            case 0x91:
6235
            case 0x92:
6236
            case 0x93:
6237
            case 0x94:
6238
            case 0x95:
6239
            case 0x96:
6240
            case 0x97:
6241
                return get_cbor_array(static_cast<std::size_t>(current & 0x1F));
6242
6243
            case 0x98: // array (one-byte uint8_t for n follows)
6244
            {
6245
                uint8_t len;
6246
                return get_number(len) and get_cbor_array(static_cast<std::size_t>(len));
6247
            }
6248
6249
            case 0x99: // array (two-byte uint16_t for n follow)
6250
            {
6251
                uint16_t len;
6252
                return get_number(len) and get_cbor_array(static_cast<std::size_t>(len));
6253
            }
6254
6255
            case 0x9A: // array (four-byte uint32_t for n follow)
6256
            {
6257
                uint32_t len;
6258
                return get_number(len) and get_cbor_array(static_cast<std::size_t>(len));
6259
            }
6260
6261
            case 0x9B: // array (eight-byte uint64_t for n follow)
6262
            {
6263
                uint64_t len;
6264
                return get_number(len) and get_cbor_array(static_cast<std::size_t>(len));
6265
            }
6266
6267
            case 0x9F: // array (indefinite length)
6268
                return get_cbor_array(std::size_t(-1));
6269
6270
            // map (0x00..0x17 pairs of data items follow)
6271
            case 0xA0:
6272
            case 0xA1:
6273
            case 0xA2:
6274
            case 0xA3:
6275
            case 0xA4:
6276
            case 0xA5:
6277
            case 0xA6:
6278
            case 0xA7:
6279
            case 0xA8:
6280
            case 0xA9:
6281
            case 0xAA:
6282
            case 0xAB:
6283
            case 0xAC:
6284
            case 0xAD:
6285
            case 0xAE:
6286
            case 0xAF:
6287
            case 0xB0:
6288
            case 0xB1:
6289
            case 0xB2:
6290
            case 0xB3:
6291
            case 0xB4:
6292
            case 0xB5:
6293
            case 0xB6:
6294
            case 0xB7:
6295
                return get_cbor_object(static_cast<std::size_t>(current & 0x1F));
6296
6297
            case 0xB8: // map (one-byte uint8_t for n follows)
6298
            {
6299
                uint8_t len;
6300
                return get_number(len) and get_cbor_object(static_cast<std::size_t>(len));
6301
            }
6302
6303
            case 0xB9: // map (two-byte uint16_t for n follow)
6304
            {
6305
                uint16_t len;
6306
                return get_number(len) and get_cbor_object(static_cast<std::size_t>(len));
6307
            }
6308
6309
            case 0xBA: // map (four-byte uint32_t for n follow)
6310
            {
6311
                uint32_t len;
6312
                return get_number(len) and get_cbor_object(static_cast<std::size_t>(len));
6313
            }
6314
6315
            case 0xBB: // map (eight-byte uint64_t for n follow)
6316
            {
6317
                uint64_t len;
6318
                return get_number(len) and get_cbor_object(static_cast<std::size_t>(len));
6319
            }
6320
6321
            case 0xBF: // map (indefinite length)
6322
                return get_cbor_object(std::size_t(-1));
6323
6324
            case 0xF4: // false
6325
                return sax->boolean(false);
6326
6327
            case 0xF5: // true
6328
                return sax->boolean(true);
6329
6330
            case 0xF6: // null
6331
                return sax->null();
6332
6333
            case 0xF9: // Half-Precision Float (two-byte IEEE 754)
6334
            {
6335
                const int byte1 = get();
6336
                if (JSON_UNLIKELY(not unexpect_eof()))
6337
                {
6338
                    return false;
6339
                }
6340
                const int byte2 = get();
6341
                if (JSON_UNLIKELY(not unexpect_eof()))
6342
                {
6343
                    return false;
6344
                }
6345
6346
                // code from RFC 7049, Appendix D, Figure 3:
6347
                // As half-precision floating-point numbers were only added
6348
                // to IEEE 754 in 2008, today's programming platforms often
6349
                // still only have limited support for them. It is very
6350
                // easy to include at least decoding support for them even
6351
                // without such support. An example of a small decoder for
6352
                // half-precision floating-point numbers in the C language
6353
                // is shown in Fig. 3.
6354
                const int half = (byte1 << 8) + byte2;
6355
                const double val = [&half]
6356
                {
6357
                    const int exp = (half >> 10) & 0x1F;
6358
                    const int mant = half & 0x3FF;
6359
                    assert(0 <= exp and exp <= 32);
6360
                    assert(0 <= mant and mant <= 1024);
6361
                    switch (exp)
6362
                    {
6363
                        case 0:
6364
                            return std::ldexp(mant, -24);
6365
                        case 31:
6366
                            return (mant == 0)
6367
                            ? std::numeric_limits<double>::infinity()
6368
                            : std::numeric_limits<double>::quiet_NaN();
6369
                        default:
6370
                            return std::ldexp(mant + 1024, exp - 25);
6371
                    }
6372
                }();
6373
                return sax->number_float((half & 0x8000) != 0
6374
                                         ? static_cast<number_float_t>(-val)
6375
                                         : static_cast<number_float_t>(val), "");
6376
            }
6377
6378
            case 0xFA: // Single-Precision Float (four-byte IEEE 754)
6379
            {
6380
                float number;
6381
                return get_number(number) and sax->number_float(static_cast<number_float_t>(number), "");
6382
            }
6383
6384
            case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
6385
            {
6386
                double number;
6387
                return get_number(number) and sax->number_float(static_cast<number_float_t>(number), "");
6388
            }
6389
6390
            default: // anything else (0xFF is handled inside the other types)
6391
            {
6392
                auto last_token = get_token_string();
6393
                return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, "error reading CBOR; last byte: 0x" + last_token));
6394
            }
6395
        }
6396
    }
6397
6398
    /*!
6399
    @return whether a valid MessagePack value was passed to the SAX parser
6400
    */
6401
    bool parse_msgpack_internal()
6402
    {
6403
        switch (get())
6404
        {
6405
            // EOF
6406
            case std::char_traits<char>::eof():
6407
                return unexpect_eof();
6408
6409
            // positive fixint
6410
            case 0x00:
6411
            case 0x01:
6412
            case 0x02:
6413
            case 0x03:
6414
            case 0x04:
6415
            case 0x05:
6416
            case 0x06:
6417
            case 0x07:
6418
            case 0x08:
6419
            case 0x09:
6420
            case 0x0A:
6421
            case 0x0B:
6422
            case 0x0C:
6423
            case 0x0D:
6424
            case 0x0E:
6425
            case 0x0F:
6426
            case 0x10:
6427
            case 0x11:
6428
            case 0x12:
6429
            case 0x13:
6430
            case 0x14:
6431
            case 0x15:
6432
            case 0x16:
6433
            case 0x17:
6434
            case 0x18:
6435
            case 0x19:
6436
            case 0x1A:
6437
            case 0x1B:
6438
            case 0x1C:
6439
            case 0x1D:
6440
            case 0x1E:
6441
            case 0x1F:
6442
            case 0x20:
6443
            case 0x21:
6444
            case 0x22:
6445
            case 0x23:
6446
            case 0x24:
6447
            case 0x25:
6448
            case 0x26:
6449
            case 0x27:
6450
            case 0x28:
6451
            case 0x29:
6452
            case 0x2A:
6453
            case 0x2B:
6454
            case 0x2C:
6455
            case 0x2D:
6456
            case 0x2E:
6457
            case 0x2F:
6458
            case 0x30:
6459
            case 0x31:
6460
            case 0x32:
6461
            case 0x33:
6462
            case 0x34:
6463
            case 0x35:
6464
            case 0x36:
6465
            case 0x37:
6466
            case 0x38:
6467
            case 0x39:
6468
            case 0x3A:
6469
            case 0x3B:
6470
            case 0x3C:
6471
            case 0x3D:
6472
            case 0x3E:
6473
            case 0x3F:
6474
            case 0x40:
6475
            case 0x41:
6476
            case 0x42:
6477
            case 0x43:
6478
            case 0x44:
6479
            case 0x45:
6480
            case 0x46:
6481
            case 0x47:
6482
            case 0x48:
6483
            case 0x49:
6484
            case 0x4A:
6485
            case 0x4B:
6486
            case 0x4C:
6487
            case 0x4D:
6488
            case 0x4E:
6489
            case 0x4F:
6490
            case 0x50:
6491
            case 0x51:
6492
            case 0x52:
6493
            case 0x53:
6494
            case 0x54:
6495
            case 0x55:
6496
            case 0x56:
6497
            case 0x57:
6498
            case 0x58:
6499
            case 0x59:
6500
            case 0x5A:
6501
            case 0x5B:
6502
            case 0x5C:
6503
            case 0x5D:
6504
            case 0x5E:
6505
            case 0x5F:
6506
            case 0x60:
6507
            case 0x61:
6508
            case 0x62:
6509
            case 0x63:
6510
            case 0x64:
6511
            case 0x65:
6512
            case 0x66:
6513
            case 0x67:
6514
            case 0x68:
6515
            case 0x69:
6516
            case 0x6A:
6517
            case 0x6B:
6518
            case 0x6C:
6519
            case 0x6D:
6520
            case 0x6E:
6521
            case 0x6F:
6522
            case 0x70:
6523
            case 0x71:
6524
            case 0x72:
6525
            case 0x73:
6526
            case 0x74:
6527
            case 0x75:
6528
            case 0x76:
6529
            case 0x77:
6530
            case 0x78:
6531
            case 0x79:
6532
            case 0x7A:
6533
            case 0x7B:
6534
            case 0x7C:
6535
            case 0x7D:
6536
            case 0x7E:
6537
            case 0x7F:
6538
                return sax->number_unsigned(static_cast<number_unsigned_t>(current));
6539
6540
            // fixmap
6541
            case 0x80:
6542
            case 0x81:
6543
            case 0x82:
6544
            case 0x83:
6545
            case 0x84:
6546
            case 0x85:
6547
            case 0x86:
6548
            case 0x87:
6549
            case 0x88:
6550
            case 0x89:
6551
            case 0x8A:
6552
            case 0x8B:
6553
            case 0x8C:
6554
            case 0x8D:
6555
            case 0x8E:
6556
            case 0x8F:
6557
                return get_msgpack_object(static_cast<std::size_t>(current & 0x0F));
6558
6559
            // fixarray
6560
            case 0x90:
6561
            case 0x91:
6562
            case 0x92:
6563
            case 0x93:
6564
            case 0x94:
6565
            case 0x95:
6566
            case 0x96:
6567
            case 0x97:
6568
            case 0x98:
6569
            case 0x99:
6570
            case 0x9A:
6571
            case 0x9B:
6572
            case 0x9C:
6573
            case 0x9D:
6574
            case 0x9E:
6575
            case 0x9F:
6576
                return get_msgpack_array(static_cast<std::size_t>(current & 0x0F));
6577
6578
            // fixstr
6579
            case 0xA0:
6580
            case 0xA1:
6581
            case 0xA2:
6582
            case 0xA3:
6583
            case 0xA4:
6584
            case 0xA5:
6585
            case 0xA6:
6586
            case 0xA7:
6587
            case 0xA8:
6588
            case 0xA9:
6589
            case 0xAA:
6590
            case 0xAB:
6591
            case 0xAC:
6592
            case 0xAD:
6593
            case 0xAE:
6594
            case 0xAF:
6595
            case 0xB0:
6596
            case 0xB1:
6597
            case 0xB2:
6598
            case 0xB3:
6599
            case 0xB4:
6600
            case 0xB5:
6601
            case 0xB6:
6602
            case 0xB7:
6603
            case 0xB8:
6604
            case 0xB9:
6605
            case 0xBA:
6606
            case 0xBB:
6607
            case 0xBC:
6608
            case 0xBD:
6609
            case 0xBE:
6610
            case 0xBF:
6611
            {
6612
                string_t s;
6613
                return get_msgpack_string(s) and sax->string(s);
6614
            }
6615
6616
            case 0xC0: // nil
6617
                return sax->null();
6618
6619
            case 0xC2: // false
6620
                return sax->boolean(false);
6621
6622
            case 0xC3: // true
6623
                return sax->boolean(true);
6624
6625
            case 0xCA: // float 32
6626
            {
6627
                float number;
6628
                return get_number(number) and sax->number_float(static_cast<number_float_t>(number), "");
6629
            }
6630
6631
            case 0xCB: // float 64
6632
            {
6633
                double number;
6634
                return get_number(number) and sax->number_float(static_cast<number_float_t>(number), "");
6635
            }
6636
6637
            case 0xCC: // uint 8
6638
            {
6639
                uint8_t number;
6640
                return get_number(number) and sax->number_unsigned(number);
6641
            }
6642
6643
            case 0xCD: // uint 16
6644
            {
6645
                uint16_t number;
6646
                return get_number(number) and sax->number_unsigned(number);
6647
            }
6648
6649
            case 0xCE: // uint 32
6650
            {
6651
                uint32_t number;
6652
                return get_number(number) and sax->number_unsigned(number);
6653
            }
6654
6655
            case 0xCF: // uint 64
6656
            {
6657
                uint64_t number;
6658
                return get_number(number) and sax->number_unsigned(number);
6659
            }
6660
6661
            case 0xD0: // int 8
6662
            {
6663
                int8_t number;
6664
                return get_number(number) and sax->number_integer(number);
6665
            }
6666
6667
            case 0xD1: // int 16
6668
            {
6669
                int16_t number;
6670
                return get_number(number) and sax->number_integer(number);
6671
            }
6672
6673
            case 0xD2: // int 32
6674
            {
6675
                int32_t number;
6676
                return get_number(number) and sax->number_integer(number);
6677
            }
6678
6679
            case 0xD3: // int 64
6680
            {
6681
                int64_t number;
6682
                return get_number(number) and sax->number_integer(number);
6683
            }
6684
6685
            case 0xD9: // str 8
6686
            case 0xDA: // str 16
6687
            case 0xDB: // str 32
6688
            {
6689
                string_t s;
6690
                return get_msgpack_string(s) and sax->string(s);
6691
            }
6692
6693
            case 0xDC: // array 16
6694
            {
6695
                uint16_t len;
6696
                return get_number(len) and get_msgpack_array(static_cast<std::size_t>(len));
6697
            }
6698
6699
            case 0xDD: // array 32
6700
            {
6701
                uint32_t len;
6702
                return get_number(len) and get_msgpack_array(static_cast<std::size_t>(len));
6703
            }
6704
6705
            case 0xDE: // map 16
6706
            {
6707
                uint16_t len;
6708
                return get_number(len) and get_msgpack_object(static_cast<std::size_t>(len));
6709
            }
6710
6711
            case 0xDF: // map 32
6712
            {
6713
                uint32_t len;
6714
                return get_number(len) and get_msgpack_object(static_cast<std::size_t>(len));
6715
            }
6716
6717
            // negative fixint
6718
            case 0xE0:
6719
            case 0xE1:
6720
            case 0xE2:
6721
            case 0xE3:
6722
            case 0xE4:
6723
            case 0xE5:
6724
            case 0xE6:
6725
            case 0xE7:
6726
            case 0xE8:
6727
            case 0xE9:
6728
            case 0xEA:
6729
            case 0xEB:
6730
            case 0xEC:
6731
            case 0xED:
6732
            case 0xEE:
6733
            case 0xEF:
6734
            case 0xF0:
6735
            case 0xF1:
6736
            case 0xF2:
6737
            case 0xF3:
6738
            case 0xF4:
6739
            case 0xF5:
6740
            case 0xF6:
6741
            case 0xF7:
6742
            case 0xF8:
6743
            case 0xF9:
6744
            case 0xFA:
6745
            case 0xFB:
6746
            case 0xFC:
6747
            case 0xFD:
6748
            case 0xFE:
6749
            case 0xFF:
6750
                return sax->number_integer(static_cast<int8_t>(current));
6751
6752
            default: // anything else
6753
            {
6754
                auto last_token = get_token_string();
6755
                return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, "error reading MessagePack; last byte: 0x" + last_token));
6756
            }
6757
        }
6758
    }
6759
6760
    /*!
6761
    @param[in] get_char  whether a new character should be retrieved from the
6762
                         input (true, default) or whether the last read
6763
                         character should be considered instead
6764
6765
    @return whether a valid UBJSON value was passed to the SAX parser
6766
    */
6767
    bool parse_ubjson_internal(const bool get_char = true)
6768
    {
6769
        return get_ubjson_value(get_char ? get_ignore_noop() : current);
6770
    }
6771
6772
    /*!
6773
    @brief get next character from the input
6774
6775
    This function provides the interface to the used input adapter. It does
6776
    not throw in case the input reached EOF, but returns a -'ve valued
6777
    `std::char_traits<char>::eof()` in that case.
6778
6779
    @return character read from the input
6780
    */
6781
    int get()
6782
    {
6783
        ++chars_read;
6784
        return (current = ia->get_character());
6785
    }
6786
6787
    /*!
6788
    @return character read from the input after ignoring all 'N' entries
6789
    */
6790
    int get_ignore_noop()
6791
    {
6792
        do
6793
        {
6794
            get();
6795
        }
6796
        while (current == 'N');
6797
6798
        return current;
6799
    }
6800
6801
    /*
6802
    @brief read a number from the input
6803
6804
    @tparam NumberType the type of the number
6805
    @param[out] result  number of type @a NumberType
6806
6807
    @return whether conversion completed
6808
6809
    @note This function needs to respect the system's endianess, because
6810
          bytes in CBOR, MessagePack, and UBJSON are stored in network order
6811
          (big endian) and therefore need reordering on little endian systems.
6812
    */
6813
    template<typename NumberType>
6814
    bool get_number(NumberType& result)
6815
    {
6816
        // step 1: read input into array with system's byte order
6817
        std::array<uint8_t, sizeof(NumberType)> vec;
6818
        for (std::size_t i = 0; i < sizeof(NumberType); ++i)
6819
        {
6820
            get();
6821
            if (JSON_UNLIKELY(not unexpect_eof()))
6822
            {
6823
                return false;
6824
            }
6825
6826
            // reverse byte order prior to conversion if necessary
6827
            if (is_little_endian)
6828
            {
6829
                vec[sizeof(NumberType) - i - 1] = static_cast<uint8_t>(current);
6830
            }
6831
            else
6832
            {
6833
                vec[i] = static_cast<uint8_t>(current); // LCOV_EXCL_LINE
6834
            }
6835
        }
6836
6837
        // step 2: convert array into number of type T and return
6838
        std::memcpy(&result, vec.data(), sizeof(NumberType));
6839
        return true;
6840
    }
6841
6842
    /*!
6843
    @brief create a string by reading characters from the input
6844
6845
    @tparam NumberType the type of the number
6846
    @param[in] len number of characters to read
6847
    @param[out] string created by reading @a len bytes
6848
6849
    @return whether string creation completed
6850
6851
    @note We can not reserve @a len bytes for the result, because @a len
6852
          may be too large. Usually, @ref unexpect_eof() detects the end of
6853
          the input before we run out of string memory.
6854
    */
6855
    template<typename NumberType>
6856
    bool get_string(const NumberType len, string_t& result)
6857
    {
6858
        bool success = true;
6859
        std::generate_n(std::back_inserter(result), len, [this, &success]()
6860
        {
6861
            get();
6862
            if (JSON_UNLIKELY(not unexpect_eof()))
6863
            {
6864
                success = false;
6865
            }
6866
            return static_cast<char>(current);
6867
        });
6868
        return success;
6869
    }
6870
6871
    /*!
6872
    @brief reads a CBOR string
6873
6874
    This function first reads starting bytes to determine the expected
6875
    string length and then copies this number of bytes into a string.
6876
    Additionally, CBOR's strings with indefinite lengths are supported.
6877
6878
    @param[out] result  created string
6879
6880
    @return whether string creation completed
6881
    */
6882
    bool get_cbor_string(string_t& result)
6883
    {
6884
        if (JSON_UNLIKELY(not unexpect_eof()))
6885
        {
6886
            return false;
6887
        }
6888
6889
        switch (current)
6890
        {
6891
            // UTF-8 string (0x00..0x17 bytes follow)
6892
            case 0x60:
6893
            case 0x61:
6894
            case 0x62:
6895
            case 0x63:
6896
            case 0x64:
6897
            case 0x65:
6898
            case 0x66:
6899
            case 0x67:
6900
            case 0x68:
6901
            case 0x69:
6902
            case 0x6A:
6903
            case 0x6B:
6904
            case 0x6C:
6905
            case 0x6D:
6906
            case 0x6E:
6907
            case 0x6F:
6908
            case 0x70:
6909
            case 0x71:
6910
            case 0x72:
6911
            case 0x73:
6912
            case 0x74:
6913
            case 0x75:
6914
            case 0x76:
6915
            case 0x77:
6916
            {
6917
                return get_string(current & 0x1F, result);
6918
            }
6919
6920
            case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
6921
            {
6922
                uint8_t len;
6923
                return get_number(len) and get_string(len, result);
6924
            }
6925
6926
            case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
6927
            {
6928
                uint16_t len;
6929
                return get_number(len) and get_string(len, result);
6930
            }
6931
6932
            case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
6933
            {
6934
                uint32_t len;
6935
                return get_number(len) and get_string(len, result);
6936
            }
6937
6938
            case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
6939
            {
6940
                uint64_t len;
6941
                return get_number(len) and get_string(len, result);
6942
            }
6943
6944
            case 0x7F: // UTF-8 string (indefinite length)
6945
            {
6946
                while (get() != 0xFF)
6947
                {
6948
                    string_t chunk;
6949
                    if (not get_cbor_string(chunk))
6950
                    {
6951
                        return false;
6952
                    }
6953
                    result.append(chunk);
6954
                }
6955
                return true;
6956
            }
6957
6958
            default:
6959
            {
6960
                auto last_token = get_token_string();
6961
                return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, "expected a CBOR string; last byte: 0x" + last_token));
6962
            }
6963
        }
6964
    }
6965
6966
    /*!
6967
    @param[in] len  the length of the array or std::size_t(-1) for an
6968
                    array of indefinite size
6969
    @return whether array creation completed
6970
    */
6971
    bool get_cbor_array(const std::size_t len)
6972
    {
6973
        if (JSON_UNLIKELY(not sax->start_array(len)))
6974
        {
6975
            return false;
6976
        }
6977
6978
        if (len != std::size_t(-1))
6979
            for (std::size_t i = 0; i < len; ++i)
6980
            {
6981
                if (JSON_UNLIKELY(not parse_cbor_internal()))
6982
                {
6983
                    return false;
6984
                }
6985
            }
6986
        else
6987
        {
6988
            while (get() != 0xFF)
6989
            {
6990
                if (JSON_UNLIKELY(not parse_cbor_internal(false)))
6991
                {
6992
                    return false;
6993
                }
6994
            }
6995
        }
6996
6997
        return sax->end_array();
6998
    }
6999
7000
    /*!
7001
    @param[in] len  the length of the object or std::size_t(-1) for an
7002
                    object of indefinite size
7003
    @return whether object creation completed
7004
    */
7005
    bool get_cbor_object(const std::size_t len)
7006
    {
7007
        if (not JSON_UNLIKELY(sax->start_object(len)))
7008
        {
7009
            return false;
7010
        }
7011
7012
        string_t key;
7013
        if (len != std::size_t(-1))
7014
        {
7015
            for (std::size_t i = 0; i < len; ++i)
7016
            {
7017
                get();
7018
                if (JSON_UNLIKELY(not get_cbor_string(key) or not sax->key(key)))
7019
                {
7020
                    return false;
7021
                }
7022
7023
                if (JSON_UNLIKELY(not parse_cbor_internal()))
7024
                {
7025
                    return false;
7026
                }
7027
                key.clear();
7028
            }
7029
        }
7030
        else
7031
        {
7032
            while (get() != 0xFF)
7033
            {
7034
                if (JSON_UNLIKELY(not get_cbor_string(key) or not sax->key(key)))
7035
                {
7036
                    return false;
7037
                }
7038
7039
                if (JSON_UNLIKELY(not parse_cbor_internal()))
7040
                {
7041
                    return false;
7042
                }
7043
                key.clear();
7044
            }
7045
        }
7046
7047
        return sax->end_object();
7048
    }
7049
7050
    /*!
7051
    @brief reads a MessagePack string
7052
7053
    This function first reads starting bytes to determine the expected
7054
    string length and then copies this number of bytes into a string.
7055
7056
    @param[out] result  created string
7057
7058
    @return whether string creation completed
7059
    */
7060
    bool get_msgpack_string(string_t& result)
7061
    {
7062
        if (JSON_UNLIKELY(not unexpect_eof()))
7063
        {
7064
            return false;
7065
        }
7066
7067
        switch (current)
7068
        {
7069
            // fixstr
7070
            case 0xA0:
7071
            case 0xA1:
7072
            case 0xA2:
7073
            case 0xA3:
7074
            case 0xA4:
7075
            case 0xA5:
7076
            case 0xA6:
7077
            case 0xA7:
7078
            case 0xA8:
7079
            case 0xA9:
7080
            case 0xAA:
7081
            case 0xAB:
7082
            case 0xAC:
7083
            case 0xAD:
7084
            case 0xAE:
7085
            case 0xAF:
7086
            case 0xB0:
7087
            case 0xB1:
7088
            case 0xB2:
7089
            case 0xB3:
7090
            case 0xB4:
7091
            case 0xB5:
7092
            case 0xB6:
7093
            case 0xB7:
7094
            case 0xB8:
7095
            case 0xB9:
7096
            case 0xBA:
7097
            case 0xBB:
7098
            case 0xBC:
7099
            case 0xBD:
7100
            case 0xBE:
7101
            case 0xBF:
7102
            {
7103
                return get_string(current & 0x1F, result);
7104
            }
7105
7106
            case 0xD9: // str 8
7107
            {
7108
                uint8_t len;
7109
                return get_number(len) and get_string(len, result);
7110
            }
7111
7112
            case 0xDA: // str 16
7113
            {
7114
                uint16_t len;
7115
                return get_number(len) and get_string(len, result);
7116
            }
7117
7118
            case 0xDB: // str 32
7119
            {
7120
                uint32_t len;
7121
                return get_number(len) and get_string(len, result);
7122
            }
7123
7124
            default:
7125
            {
7126
                auto last_token = get_token_string();
7127
                return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, "expected a MessagePack string; last byte: 0x" + last_token));
7128
            }
7129
        }
7130
    }
7131
7132
    /*!
7133
    @param[in] len  the length of the array
7134
    @return whether array creation completed
7135
    */
7136
    bool get_msgpack_array(const std::size_t len)
7137
    {
7138
        if (JSON_UNLIKELY(not sax->start_array(len)))
7139
        {
7140
            return false;
7141
        }
7142
7143
        for (std::size_t i = 0; i < len; ++i)
7144
        {
7145
            if (JSON_UNLIKELY(not parse_msgpack_internal()))
7146
            {
7147
                return false;
7148
            }
7149
        }
7150
7151
        return sax->end_array();
7152
    }
7153
7154
    /*!
7155
    @param[in] len  the length of the object
7156
    @return whether object creation completed
7157
    */
7158
    bool get_msgpack_object(const std::size_t len)
7159
    {
7160
        if (JSON_UNLIKELY(not sax->start_object(len)))
7161
        {
7162
            return false;
7163
        }
7164
7165
        string_t key;
7166
        for (std::size_t i = 0; i < len; ++i)
7167
        {
7168
            get();
7169
            if (JSON_UNLIKELY(not get_msgpack_string(key) or not sax->key(key)))
7170
            {
7171
                return false;
7172
            }
7173
7174
            if (JSON_UNLIKELY(not parse_msgpack_internal()))
7175
            {
7176
                return false;
7177
            }
7178
            key.clear();
7179
        }
7180
7181
        return sax->end_object();
7182
    }
7183
7184
    /*!
7185
    @brief reads a UBJSON string
7186
7187
    This function is either called after reading the 'S' byte explicitly
7188
    indicating a string, or in case of an object key where the 'S' byte can be
7189
    left out.
7190
7191
    @param[out] result   created string
7192
    @param[in] get_char  whether a new character should be retrieved from the
7193
                         input (true, default) or whether the last read
7194
                         character should be considered instead
7195
7196
    @return whether string creation completed
7197
    */
7198
    bool get_ubjson_string(string_t& result, const bool get_char = true)
7199
    {
7200
        if (get_char)
7201
        {
7202
            get();  // TODO: may we ignore N here?
7203
        }
7204
7205
        if (JSON_UNLIKELY(not unexpect_eof()))
7206
        {
7207
            return false;
7208
        }
7209
7210
        switch (current)
7211
        {
7212
            case 'U':
7213
            {
7214
                uint8_t len;
7215
                return get_number(len) and get_string(len, result);
7216
            }
7217
7218
            case 'i':
7219
            {
7220
                int8_t len;
7221
                return get_number(len) and get_string(len, result);
7222
            }
7223
7224
            case 'I':
7225
            {
7226
                int16_t len;
7227
                return get_number(len) and get_string(len, result);
7228
            }
7229
7230
            case 'l':
7231
            {
7232
                int32_t len;
7233
                return get_number(len) and get_string(len, result);
7234
            }
7235
7236
            case 'L':
7237
            {
7238
                int64_t len;
7239
                return get_number(len) and get_string(len, result);
7240
            }
7241
7242
            default:
7243
                auto last_token = get_token_string();
7244
                return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, "expected a UBJSON string; last byte: 0x" + last_token));
7245
        }
7246
    }
7247
7248
    /*!
7249
    @param[out] result  determined size
7250
    @return whether size determination completed
7251
    */
7252
    bool get_ubjson_size_value(std::size_t& result)
7253
    {
7254
        switch (get_ignore_noop())
7255
        {
7256
            case 'U':
7257
            {
7258
                uint8_t number;
7259
                if (JSON_UNLIKELY(not get_number(number)))
7260
                {
7261
                    return false;
7262
                }
7263
                result = static_cast<std::size_t>(number);
7264
                return true;
7265
            }
7266
7267
            case 'i':
7268
            {
7269
                int8_t number;
7270
                if (JSON_UNLIKELY(not get_number(number)))
7271
                {
7272
                    return false;
7273
                }
7274
                result = static_cast<std::size_t>(number);
7275
                return true;
7276
            }
7277
7278
            case 'I':
7279
            {
7280
                int16_t number;
7281
                if (JSON_UNLIKELY(not get_number(number)))
7282
                {
7283
                    return false;
7284
                }
7285
                result = static_cast<std::size_t>(number);
7286
                return true;
7287
            }
7288
7289
            case 'l':
7290
            {
7291
                int32_t number;
7292
                if (JSON_UNLIKELY(not get_number(number)))
7293
                {
7294
                    return false;
7295
                }
7296
                result = static_cast<std::size_t>(number);
7297
                return true;
7298
            }
7299
7300
            case 'L':
7301
            {
7302
                int64_t number;
7303
                if (JSON_UNLIKELY(not get_number(number)))
7304
                {
7305
                    return false;
7306
                }
7307
                result = static_cast<std::size_t>(number);
7308
                return true;
7309
            }
7310
7311
            default:
7312
            {
7313
                auto last_token = get_token_string();
7314
                return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, "byte after '#' must denote a number type; last byte: 0x" + last_token));
7315
            }
7316
        }
7317
    }
7318
7319
    /*!
7320
    @brief determine the type and size for a container
7321
7322
    In the optimized UBJSON format, a type and a size can be provided to allow
7323
    for a more compact representation.
7324
7325
    @param[out] result  pair of the size and the type
7326
7327
    @return whether pair creation completed
7328
    */
7329
    bool get_ubjson_size_type(std::pair<std::size_t, int>& result)
7330
    {
7331
        result.first = string_t::npos; // size
7332
        result.second = 0; // type
7333
7334
        get_ignore_noop();
7335
7336
        if (current == '$')
7337
        {
7338
            result.second = get();  // must not ignore 'N', because 'N' maybe the type
7339
            if (JSON_UNLIKELY(not unexpect_eof()))
7340
            {
7341
                return false;
7342
            }
7343
7344
            get_ignore_noop();
7345
            if (JSON_UNLIKELY(current != '#'))
7346
            {
7347
                if (JSON_UNLIKELY(not unexpect_eof()))
7348
                {
7349
                    return false;
7350
                }
7351
                auto last_token = get_token_string();
7352
                return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, "expected '#' after UBJSON type information; last byte: 0x" + last_token));
7353
            }
7354
7355
            return get_ubjson_size_value(result.first);
7356
        }
7357
        else if (current == '#')
7358
        {
7359
            return get_ubjson_size_value(result.first);
7360
        }
7361
        return true;
7362
    }
7363
7364
    /*!
7365
    @param prefix  the previously read or set type prefix
7366
    @return whether value creation completed
7367
    */
7368
    bool get_ubjson_value(const int prefix)
7369
    {
7370
        switch (prefix)
7371
        {
7372
            case std::char_traits<char>::eof():  // EOF
7373
                return unexpect_eof();
7374
7375
            case 'T':  // true
7376
                return sax->boolean(true);
7377
            case 'F':  // false
7378
                return sax->boolean(false);
7379
7380
            case 'Z':  // null
7381
                return sax->null();
7382
7383
            case 'U':
7384
            {
7385
                uint8_t number;
7386
                return get_number(number) and sax->number_unsigned(number);
7387
            }
7388
7389
            case 'i':
7390
            {
7391
                int8_t number;
7392
                return get_number(number) and sax->number_integer(number);
7393
            }
7394
7395
            case 'I':
7396
            {
7397
                int16_t number;
7398
                return get_number(number) and sax->number_integer(number);
7399
            }
7400
7401
            case 'l':
7402
            {
7403
                int32_t number;
7404
                return get_number(number) and sax->number_integer(number);
7405
            }
7406
7407
            case 'L':
7408
            {
7409
                int64_t number;
7410
                return get_number(number) and sax->number_integer(number);
7411
            }
7412
7413
            case 'd':
7414
            {
7415
                float number;
7416
                return get_number(number) and sax->number_float(static_cast<number_float_t>(number), "");
7417
            }
7418
7419
            case 'D':
7420
            {
7421
                double number;
7422
                return get_number(number) and sax->number_float(static_cast<number_float_t>(number), "");
7423
            }
7424
7425
            case 'C':  // char
7426
            {
7427
                get();
7428
                if (JSON_UNLIKELY(not unexpect_eof()))
7429
                {
7430
                    return false;
7431
                }
7432
                if (JSON_UNLIKELY(current > 127))
7433
                {
7434
                    auto last_token = get_token_string();
7435
                    return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + last_token));
7436
                }
7437
                string_t s(1, static_cast<char>(current));
7438
                return sax->string(s);
7439
            }
7440
7441
            case 'S':  // string
7442
            {
7443
                string_t s;
7444
                return get_ubjson_string(s) and sax->string(s);
7445
            }
7446
7447
            case '[':  // array
7448
                return get_ubjson_array();
7449
7450
            case '{':  // object
7451
                return get_ubjson_object();
7452
7453
            default: // anything else
7454
            {
7455
                auto last_token = get_token_string();
7456
                return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, "error reading UBJSON; last byte: 0x" + last_token));
7457
            }
7458
        }
7459
    }
7460
7461
    /*!
7462
    @return whether array creation completed
7463
    */
7464
    bool get_ubjson_array()
7465
    {
7466
        std::pair<std::size_t, int> size_and_type;
7467
        if (JSON_UNLIKELY(not get_ubjson_size_type(size_and_type)))
7468
        {
7469
            return false;
7470
        }
7471
7472
        if (size_and_type.first != string_t::npos)
7473
        {
7474
            if (JSON_UNLIKELY(not sax->start_array(size_and_type.first)))
7475
            {
7476
                return false;
7477
            }
7478
7479
            if (size_and_type.second != 0)
7480
            {
7481
                if (size_and_type.second != 'N')
7482
                {
7483
                    for (std::size_t i = 0; i < size_and_type.first; ++i)
7484
                    {
7485
                        if (JSON_UNLIKELY(not get_ubjson_value(size_and_type.second)))
7486
                        {
7487
                            return false;
7488
                        }
7489
                    }
7490
                }
7491
            }
7492
            else
7493
            {
7494
                for (std::size_t i = 0; i < size_and_type.first; ++i)
7495
                {
7496
                    if (JSON_UNLIKELY(not parse_ubjson_internal()))
7497
                    {
7498
                        return false;
7499
                    }
7500
                }
7501
            }
7502
        }
7503
        else
7504
        {
7505
            if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1))))
7506
            {
7507
                return false;
7508
            }
7509
7510
            while (current != ']')
7511
            {
7512
                if (JSON_UNLIKELY(not parse_ubjson_internal(false)))
7513
                {
7514
                    return false;
7515
                }
7516
                get_ignore_noop();
7517
            }
7518
        }
7519
7520
        return sax->end_array();
7521
    }
7522
7523
    /*!
7524
    @return whether object creation completed
7525
    */
7526
    bool get_ubjson_object()
7527
    {
7528
        std::pair<std::size_t, int> size_and_type;
7529
        if (JSON_UNLIKELY(not get_ubjson_size_type(size_and_type)))
7530
        {
7531
            return false;
7532
        }
7533
7534
        string_t key;
7535
        if (size_and_type.first != string_t::npos)
7536
        {
7537
            if (JSON_UNLIKELY(not sax->start_object(size_and_type.first)))
7538
            {
7539
                return false;
7540
            }
7541
7542
            if (size_and_type.second != 0)
7543
            {
7544
                for (std::size_t i = 0; i < size_and_type.first; ++i)
7545
                {
7546
                    if (JSON_UNLIKELY(not get_ubjson_string(key) or not sax->key(key)))
7547
                    {
7548
                        return false;
7549
                    }
7550
                    if (JSON_UNLIKELY(not get_ubjson_value(size_and_type.second)))
7551
                    {
7552
                        return false;
7553
                    }
7554
                    key.clear();
7555
                }
7556
            }
7557
            else
7558
            {
7559
                for (std::size_t i = 0; i < size_and_type.first; ++i)
7560
                {
7561
                    if (JSON_UNLIKELY(not get_ubjson_string(key) or not sax->key(key)))
7562
                    {
7563
                        return false;
7564
                    }
7565
                    if (JSON_UNLIKELY(not parse_ubjson_internal()))
7566
                    {
7567
                        return false;
7568
                    }
7569
                    key.clear();
7570
                }
7571
            }
7572
        }
7573
        else
7574
        {
7575
            if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1))))
7576
            {
7577
                return false;
7578
            }
7579
7580
            while (current != '}')
7581
            {
7582
                if (JSON_UNLIKELY(not get_ubjson_string(key, false) or not sax->key(key)))
7583
                {
7584
                    return false;
7585
                }
7586
                if (JSON_UNLIKELY(not parse_ubjson_internal()))
7587
                {
7588
                    return false;
7589
                }
7590
                get_ignore_noop();
7591
                key.clear();
7592
            }
7593
        }
7594
7595
        return sax->end_object();
7596
    }
7597
7598
    /*!
7599
    @return whether the last read character is not EOF
7600
    */
7601
    bool unexpect_eof() const
7602
    {
7603
        if (JSON_UNLIKELY(current == std::char_traits<char>::eof()))
7604
        {
7605
            return sax->parse_error(chars_read, "<end of file>", parse_error::create(110, chars_read, "unexpected end of input"));
7606
        }
7607
        return true;
7608
    }
7609
7610
    /*!
7611
    @return a string representation of the last read byte
7612
    */
7613
    std::string get_token_string() const
7614
    {
7615
        char cr[3];
7616
        snprintf(cr, 3, "%.2hhX", static_cast<unsigned char>(current));
7617
        return std::string{cr};
7618
    }
7619
7620
  private:
7621
    /// input adapter
7622
    input_adapter_t ia = nullptr;
7623
7624
    /// the current character
7625
    int current = std::char_traits<char>::eof();
7626
7627
    /// the number of characters read
7628
    std::size_t chars_read = 0;
7629
7630
    /// whether we can assume little endianess
7631
    const bool is_little_endian = little_endianess();
7632
7633
    /// the SAX parser
7634
    json_sax_t* sax = nullptr;
7635
};
7636
}
7637
}
7638
7639
// #include <nlohmann/detail/output/binary_writer.hpp>
7640
7641
7642
#include <algorithm> // reverse
7643
#include <array> // array
7644
#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
7645
#include <cstring> // memcpy
7646
#include <limits> // numeric_limits
7647
7648
// #include <nlohmann/detail/input/binary_reader.hpp>
7649
7650
// #include <nlohmann/detail/output/output_adapters.hpp>
7651
7652
7653
namespace nlohmann
7654
{
7655
namespace detail
7656
{
7657
///////////////////
7658
// binary writer //
7659
///////////////////
7660
7661
/*!
7662
@brief serialization to CBOR and MessagePack values
7663
*/
7664
template<typename BasicJsonType, typename CharType>
7665
class binary_writer
7666
{
7667
  public:
7668
    /*!
7669
    @brief create a binary writer
7670
7671
    @param[in] adapter  output adapter to write to
7672
    */
7673
    explicit binary_writer(output_adapter_t<CharType> adapter) : oa(adapter)
7674
    {
7675
        assert(oa);
7676
    }
7677
7678
    /*!
7679
    @brief[in] j  JSON value to serialize
7680
    */
7681
    void write_cbor(const BasicJsonType& j)
7682
    {
7683
        switch (j.type())
7684
        {
7685
            case value_t::null:
7686
            {
7687
                oa->write_character(static_cast<CharType>(0xF6));
7688
                break;
7689
            }
7690
7691
            case value_t::boolean:
7692
            {
7693
                oa->write_character(j.m_value.boolean
7694
                                    ? static_cast<CharType>(0xF5)
7695
                                    : static_cast<CharType>(0xF4));
7696
                break;
7697
            }
7698
7699
            case value_t::number_integer:
7700
            {
7701
                if (j.m_value.number_integer >= 0)
7702
                {
7703
                    // CBOR does not differentiate between positive signed
7704
                    // integers and unsigned integers. Therefore, we used the
7705
                    // code from the value_t::number_unsigned case here.
7706
                    if (j.m_value.number_integer <= 0x17)
7707
                    {
7708
                        write_number(static_cast<uint8_t>(j.m_value.number_integer));
7709
                    }
7710
                    else if (j.m_value.number_integer <= (std::numeric_limits<uint8_t>::max)())
7711
                    {
7712
                        oa->write_character(static_cast<CharType>(0x18));
7713
                        write_number(static_cast<uint8_t>(j.m_value.number_integer));
7714
                    }
7715
                    else if (j.m_value.number_integer <= (std::numeric_limits<uint16_t>::max)())
7716
                    {
7717
                        oa->write_character(static_cast<CharType>(0x19));
7718
                        write_number(static_cast<uint16_t>(j.m_value.number_integer));
7719
                    }
7720
                    else if (j.m_value.number_integer <= (std::numeric_limits<uint32_t>::max)())
7721
                    {
7722
                        oa->write_character(static_cast<CharType>(0x1A));
7723
                        write_number(static_cast<uint32_t>(j.m_value.number_integer));
7724
                    }
7725
                    else
7726
                    {
7727
                        oa->write_character(static_cast<CharType>(0x1B));
7728
                        write_number(static_cast<uint64_t>(j.m_value.number_integer));
7729
                    }
7730
                }
7731
                else
7732
                {
7733
                    // The conversions below encode the sign in the first
7734
                    // byte, and the value is converted to a positive number.
7735
                    const auto positive_number = -1 - j.m_value.number_integer;
7736
                    if (j.m_value.number_integer >= -24)
7737
                    {
7738
                        write_number(static_cast<uint8_t>(0x20 + positive_number));
7739
                    }
7740
                    else if (positive_number <= (std::numeric_limits<uint8_t>::max)())
7741
                    {
7742
                        oa->write_character(static_cast<CharType>(0x38));
7743
                        write_number(static_cast<uint8_t>(positive_number));
7744
                    }
7745
                    else if (positive_number <= (std::numeric_limits<uint16_t>::max)())
7746
                    {
7747
                        oa->write_character(static_cast<CharType>(0x39));
7748
                        write_number(static_cast<uint16_t>(positive_number));
7749
                    }
7750
                    else if (positive_number <= (std::numeric_limits<uint32_t>::max)())
7751
                    {
7752
                        oa->write_character(static_cast<CharType>(0x3A));
7753
                        write_number(static_cast<uint32_t>(positive_number));
7754
                    }
7755
                    else
7756
                    {
7757
                        oa->write_character(static_cast<CharType>(0x3B));
7758
                        write_number(static_cast<uint64_t>(positive_number));
7759
                    }
7760
                }
7761
                break;
7762
            }
7763
7764
            case value_t::number_unsigned:
7765
            {
7766
                if (j.m_value.number_unsigned <= 0x17)
7767
                {
7768
                    write_number(static_cast<uint8_t>(j.m_value.number_unsigned));
7769
                }
7770
                else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
7771
                {
7772
                    oa->write_character(static_cast<CharType>(0x18));
7773
                    write_number(static_cast<uint8_t>(j.m_value.number_unsigned));
7774
                }
7775
                else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
7776
                {
7777
                    oa->write_character(static_cast<CharType>(0x19));
7778
                    write_number(static_cast<uint16_t>(j.m_value.number_unsigned));
7779
                }
7780
                else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
7781
                {
7782
                    oa->write_character(static_cast<CharType>(0x1A));
7783
                    write_number(static_cast<uint32_t>(j.m_value.number_unsigned));
7784
                }
7785
                else
7786
                {
7787
                    oa->write_character(static_cast<CharType>(0x1B));
7788
                    write_number(static_cast<uint64_t>(j.m_value.number_unsigned));
7789
                }
7790
                break;
7791
            }
7792
7793
            case value_t::number_float:
7794
            {
7795
                oa->write_character(get_cbor_float_prefix(j.m_value.number_float));
7796
                write_number(j.m_value.number_float);
7797
                break;
7798
            }
7799
7800
            case value_t::string:
7801
            {
7802
                // step 1: write control byte and the string length
7803
                const auto N = j.m_value.string->size();
7804
                if (N <= 0x17)
7805
                {
7806
                    write_number(static_cast<uint8_t>(0x60 + N));
7807
                }
7808
                else if (N <= (std::numeric_limits<uint8_t>::max)())
7809
                {
7810
                    oa->write_character(static_cast<CharType>(0x78));
7811
                    write_number(static_cast<uint8_t>(N));
7812
                }
7813
                else if (N <= (std::numeric_limits<uint16_t>::max)())
7814
                {
7815
                    oa->write_character(static_cast<CharType>(0x79));
7816
                    write_number(static_cast<uint16_t>(N));
7817
                }
7818
                else if (N <= (std::numeric_limits<uint32_t>::max)())
7819
                {
7820
                    oa->write_character(static_cast<CharType>(0x7A));
7821
                    write_number(static_cast<uint32_t>(N));
7822
                }
7823
                // LCOV_EXCL_START
7824
                else if (N <= (std::numeric_limits<uint64_t>::max)())
7825
                {
7826
                    oa->write_character(static_cast<CharType>(0x7B));
7827
                    write_number(static_cast<uint64_t>(N));
7828
                }
7829
                // LCOV_EXCL_STOP
7830
7831
                // step 2: write the string
7832
                oa->write_characters(
7833
                    reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
7834
                    j.m_value.string->size());
7835
                break;
7836
            }
7837
7838
            case value_t::array:
7839
            {
7840
                // step 1: write control byte and the array size
7841
                const auto N = j.m_value.array->size();
7842
                if (N <= 0x17)
7843
                {
7844
                    write_number(static_cast<uint8_t>(0x80 + N));
7845
                }
7846
                else if (N <= (std::numeric_limits<uint8_t>::max)())
7847
                {
7848
                    oa->write_character(static_cast<CharType>(0x98));
7849
                    write_number(static_cast<uint8_t>(N));
7850
                }
7851
                else if (N <= (std::numeric_limits<uint16_t>::max)())
7852
                {
7853
                    oa->write_character(static_cast<CharType>(0x99));
7854
                    write_number(static_cast<uint16_t>(N));
7855
                }
7856
                else if (N <= (std::numeric_limits<uint32_t>::max)())
7857
                {
7858
                    oa->write_character(static_cast<CharType>(0x9A));
7859
                    write_number(static_cast<uint32_t>(N));
7860
                }
7861
                // LCOV_EXCL_START
7862
                else if (N <= (std::numeric_limits<uint64_t>::max)())
7863
                {
7864
                    oa->write_character(static_cast<CharType>(0x9B));
7865
                    write_number(static_cast<uint64_t>(N));
7866
                }
7867
                // LCOV_EXCL_STOP
7868
7869
                // step 2: write each element
7870
                for (const auto& el : *j.m_value.array)
7871
                {
7872
                    write_cbor(el);
7873
                }
7874
                break;
7875
            }
7876
7877
            case value_t::object:
7878
            {
7879
                // step 1: write control byte and the object size
7880
                const auto N = j.m_value.object->size();
7881
                if (N <= 0x17)
7882
                {
7883
                    write_number(static_cast<uint8_t>(0xA0 + N));
7884
                }
7885
                else if (N <= (std::numeric_limits<uint8_t>::max)())
7886
                {
7887
                    oa->write_character(static_cast<CharType>(0xB8));
7888
                    write_number(static_cast<uint8_t>(N));
7889
                }
7890
                else if (N <= (std::numeric_limits<uint16_t>::max)())
7891
                {
7892
                    oa->write_character(static_cast<CharType>(0xB9));
7893
                    write_number(static_cast<uint16_t>(N));
7894
                }
7895
                else if (N <= (std::numeric_limits<uint32_t>::max)())
7896
                {
7897
                    oa->write_character(static_cast<CharType>(0xBA));
7898
                    write_number(static_cast<uint32_t>(N));
7899
                }
7900
                // LCOV_EXCL_START
7901
                else if (N <= (std::numeric_limits<uint64_t>::max)())
7902
                {
7903
                    oa->write_character(static_cast<CharType>(0xBB));
7904
                    write_number(static_cast<uint64_t>(N));
7905
                }
7906
                // LCOV_EXCL_STOP
7907
7908
                // step 2: write each element
7909
                for (const auto& el : *j.m_value.object)
7910
                {
7911
                    write_cbor(el.first);
7912
                    write_cbor(el.second);
7913
                }
7914
                break;
7915
            }
7916
7917
            default:
7918
                break;
7919
        }
7920
    }
7921
7922
    /*!
7923
    @brief[in] j  JSON value to serialize
7924
    */
7925
    void write_msgpack(const BasicJsonType& j)
7926
    {
7927
        switch (j.type())
7928
        {
7929
            case value_t::null: // nil
7930
            {
7931
                oa->write_character(static_cast<CharType>(0xC0));
7932
                break;
7933
            }
7934
7935
            case value_t::boolean: // true and false
7936
            {
7937
                oa->write_character(j.m_value.boolean
7938
                                    ? static_cast<CharType>(0xC3)
7939
                                    : static_cast<CharType>(0xC2));
7940
                break;
7941
            }
7942
7943
            case value_t::number_integer:
7944
            {
7945
                if (j.m_value.number_integer >= 0)
7946
                {
7947
                    // MessagePack does not differentiate between positive
7948
                    // signed integers and unsigned integers. Therefore, we used
7949
                    // the code from the value_t::number_unsigned case here.
7950
                    if (j.m_value.number_unsigned < 128)
7951
                    {
7952
                        // positive fixnum
7953
                        write_number(static_cast<uint8_t>(j.m_value.number_integer));
7954
                    }
7955
                    else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
7956
                    {
7957
                        // uint 8
7958
                        oa->write_character(static_cast<CharType>(0xCC));
7959
                        write_number(static_cast<uint8_t>(j.m_value.number_integer));
7960
                    }
7961
                    else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
7962
                    {
7963
                        // uint 16
7964
                        oa->write_character(static_cast<CharType>(0xCD));
7965
                        write_number(static_cast<uint16_t>(j.m_value.number_integer));
7966
                    }
7967
                    else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
7968
                    {
7969
                        // uint 32
7970
                        oa->write_character(static_cast<CharType>(0xCE));
7971
                        write_number(static_cast<uint32_t>(j.m_value.number_integer));
7972
                    }
7973
                    else if (j.m_value.number_unsigned <= (std::numeric_limits<uint64_t>::max)())
7974
                    {
7975
                        // uint 64
7976
                        oa->write_character(static_cast<CharType>(0xCF));
7977
                        write_number(static_cast<uint64_t>(j.m_value.number_integer));
7978
                    }
7979
                }
7980
                else
7981
                {
7982
                    if (j.m_value.number_integer >= -32)
7983
                    {
7984
                        // negative fixnum
7985
                        write_number(static_cast<int8_t>(j.m_value.number_integer));
7986
                    }
7987
                    else if (j.m_value.number_integer >= (std::numeric_limits<int8_t>::min)() and
7988
                             j.m_value.number_integer <= (std::numeric_limits<int8_t>::max)())
7989
                    {
7990
                        // int 8
7991
                        oa->write_character(static_cast<CharType>(0xD0));
7992
                        write_number(static_cast<int8_t>(j.m_value.number_integer));
7993
                    }
7994
                    else if (j.m_value.number_integer >= (std::numeric_limits<int16_t>::min)() and
7995
                             j.m_value.number_integer <= (std::numeric_limits<int16_t>::max)())
7996
                    {
7997
                        // int 16
7998
                        oa->write_character(static_cast<CharType>(0xD1));
7999
                        write_number(static_cast<int16_t>(j.m_value.number_integer));
8000
                    }
8001
                    else if (j.m_value.number_integer >= (std::numeric_limits<int32_t>::min)() and
8002
                             j.m_value.number_integer <= (std::numeric_limits<int32_t>::max)())
8003
                    {
8004
                        // int 32
8005
                        oa->write_character(static_cast<CharType>(0xD2));
8006
                        write_number(static_cast<int32_t>(j.m_value.number_integer));
8007
                    }
8008
                    else if (j.m_value.number_integer >= (std::numeric_limits<int64_t>::min)() and
8009
                             j.m_value.number_integer <= (std::numeric_limits<int64_t>::max)())
8010
                    {
8011
                        // int 64
8012
                        oa->write_character(static_cast<CharType>(0xD3));
8013
                        write_number(static_cast<int64_t>(j.m_value.number_integer));
8014
                    }
8015
                }
8016
                break;
8017
            }
8018
8019
            case value_t::number_unsigned:
8020
            {
8021
                if (j.m_value.number_unsigned < 128)
8022
                {
8023
                    // positive fixnum
8024
                    write_number(static_cast<uint8_t>(j.m_value.number_integer));
8025
                }
8026
                else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
8027
                {
8028
                    // uint 8
8029
                    oa->write_character(static_cast<CharType>(0xCC));
8030
                    write_number(static_cast<uint8_t>(j.m_value.number_integer));
8031
                }
8032
                else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
8033
                {
8034
                    // uint 16
8035
                    oa->write_character(static_cast<CharType>(0xCD));
8036
                    write_number(static_cast<uint16_t>(j.m_value.number_integer));
8037
                }
8038
                else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
8039
                {
8040
                    // uint 32
8041
                    oa->write_character(static_cast<CharType>(0xCE));
8042
                    write_number(static_cast<uint32_t>(j.m_value.number_integer));
8043
                }
8044
                else if (j.m_value.number_unsigned <= (std::numeric_limits<uint64_t>::max)())
8045
                {
8046
                    // uint 64
8047
                    oa->write_character(static_cast<CharType>(0xCF));
8048
                    write_number(static_cast<uint64_t>(j.m_value.number_integer));
8049
                }
8050
                break;
8051
            }
8052
8053
            case value_t::number_float:
8054
            {
8055
                oa->write_character(get_msgpack_float_prefix(j.m_value.number_float));
8056
                write_number(j.m_value.number_float);
8057
                break;
8058
            }
8059
8060
            case value_t::string:
8061
            {
8062
                // step 1: write control byte and the string length
8063
                const auto N = j.m_value.string->size();
8064
                if (N <= 31)
8065
                {
8066
                    // fixstr
8067
                    write_number(static_cast<uint8_t>(0xA0 | N));
8068
                }
8069
                else if (N <= (std::numeric_limits<uint8_t>::max)())
8070
                {
8071
                    // str 8
8072
                    oa->write_character(static_cast<CharType>(0xD9));
8073
                    write_number(static_cast<uint8_t>(N));
8074
                }
8075
                else if (N <= (std::numeric_limits<uint16_t>::max)())
8076
                {
8077
                    // str 16
8078
                    oa->write_character(static_cast<CharType>(0xDA));
8079
                    write_number(static_cast<uint16_t>(N));
8080
                }
8081
                else if (N <= (std::numeric_limits<uint32_t>::max)())
8082
                {
8083
                    // str 32
8084
                    oa->write_character(static_cast<CharType>(0xDB));
8085
                    write_number(static_cast<uint32_t>(N));
8086
                }
8087
8088
                // step 2: write the string
8089
                oa->write_characters(
8090
                    reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
8091
                    j.m_value.string->size());
8092
                break;
8093
            }
8094
8095
            case value_t::array:
8096
            {
8097
                // step 1: write control byte and the array size
8098
                const auto N = j.m_value.array->size();
8099
                if (N <= 15)
8100
                {
8101
                    // fixarray
8102
                    write_number(static_cast<uint8_t>(0x90 | N));
8103
                }
8104
                else if (N <= (std::numeric_limits<uint16_t>::max)())
8105
                {
8106
                    // array 16
8107
                    oa->write_character(static_cast<CharType>(0xDC));
8108
                    write_number(static_cast<uint16_t>(N));
8109
                }
8110
                else if (N <= (std::numeric_limits<uint32_t>::max)())
8111
                {
8112
                    // array 32
8113
                    oa->write_character(static_cast<CharType>(0xDD));
8114
                    write_number(static_cast<uint32_t>(N));
8115
                }
8116
8117
                // step 2: write each element
8118
                for (const auto& el : *j.m_value.array)
8119
                {
8120
                    write_msgpack(el);
8121
                }
8122
                break;
8123
            }
8124
8125
            case value_t::object:
8126
            {
8127
                // step 1: write control byte and the object size
8128
                const auto N = j.m_value.object->size();
8129
                if (N <= 15)
8130
                {
8131
                    // fixmap
8132
                    write_number(static_cast<uint8_t>(0x80 | (N & 0xF)));
8133
                }
8134
                else if (N <= (std::numeric_limits<uint16_t>::max)())
8135
                {
8136
                    // map 16
8137
                    oa->write_character(static_cast<CharType>(0xDE));
8138
                    write_number(static_cast<uint16_t>(N));
8139
                }
8140
                else if (N <= (std::numeric_limits<uint32_t>::max)())
8141
                {
8142
                    // map 32
8143
                    oa->write_character(static_cast<CharType>(0xDF));
8144
                    write_number(static_cast<uint32_t>(N));
8145
                }
8146
8147
                // step 2: write each element
8148
                for (const auto& el : *j.m_value.object)
8149
                {
8150
                    write_msgpack(el.first);
8151
                    write_msgpack(el.second);
8152
                }
8153
                break;
8154
            }
8155
8156
            default:
8157
                break;
8158
        }
8159
    }
8160
8161
    /*!
8162
    @param[in] j  JSON value to serialize
8163
    @param[in] use_count   whether to use '#' prefixes (optimized format)
8164
    @param[in] use_type    whether to use '$' prefixes (optimized format)
8165
    @param[in] add_prefix  whether prefixes need to be used for this value
8166
    */
8167
    void write_ubjson(const BasicJsonType& j, const bool use_count,
8168
                      const bool use_type, const bool add_prefix = true)
8169
    {
8170
        switch (j.type())
8171
        {
8172
            case value_t::null:
8173
            {
8174
                if (add_prefix)
8175
                {
8176
                    oa->write_character(static_cast<CharType>('Z'));
8177
                }
8178
                break;
8179
            }
8180
8181
            case value_t::boolean:
8182
            {
8183
                if (add_prefix)
8184
                    oa->write_character(j.m_value.boolean
8185
                                        ? static_cast<CharType>('T')
8186
                                        : static_cast<CharType>('F'));
8187
                break;
8188
            }
8189
8190
            case value_t::number_integer:
8191
            {
8192
                write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix);
8193
                break;
8194
            }
8195
8196
            case value_t::number_unsigned:
8197
            {
8198
                write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix);
8199
                break;
8200
            }
8201
8202
            case value_t::number_float:
8203
            {
8204
                write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix);
8205
                break;
8206
            }
8207
8208
            case value_t::string:
8209
            {
8210
                if (add_prefix)
8211
                {
8212
                    oa->write_character(static_cast<CharType>('S'));
8213
                }
8214
                write_number_with_ubjson_prefix(j.m_value.string->size(), true);
8215
                oa->write_characters(
8216
                    reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
8217
                    j.m_value.string->size());
8218
                break;
8219
            }
8220
8221
            case value_t::array:
8222
            {
8223
                if (add_prefix)
8224
                {
8225
                    oa->write_character(static_cast<CharType>('['));
8226
                }
8227
8228
                bool prefix_required = true;
8229
                if (use_type and not j.m_value.array->empty())
8230
                {
8231
                    assert(use_count);
8232
                    const CharType first_prefix = ubjson_prefix(j.front());
8233
                    const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
8234
                                                         [this, first_prefix](const BasicJsonType & v)
8235
                    {
8236
                        return ubjson_prefix(v) == first_prefix;
8237
                    });
8238
8239
                    if (same_prefix)
8240
                    {
8241
                        prefix_required = false;
8242
                        oa->write_character(static_cast<CharType>('$'));
8243
                        oa->write_character(first_prefix);
8244
                    }
8245
                }
8246
8247
                if (use_count)
8248
                {
8249
                    oa->write_character(static_cast<CharType>('#'));
8250
                    write_number_with_ubjson_prefix(j.m_value.array->size(), true);
8251
                }
8252
8253
                for (const auto& el : *j.m_value.array)
8254
                {
8255
                    write_ubjson(el, use_count, use_type, prefix_required);
8256
                }
8257
8258
                if (not use_count)
8259
                {
8260
                    oa->write_character(static_cast<CharType>(']'));
8261
                }
8262
8263
                break;
8264
            }
8265
8266
            case value_t::object:
8267
            {
8268
                if (add_prefix)
8269
                {
8270
                    oa->write_character(static_cast<CharType>('{'));
8271
                }
8272
8273
                bool prefix_required = true;
8274
                if (use_type and not j.m_value.object->empty())
8275
                {
8276
                    assert(use_count);
8277
                    const CharType first_prefix = ubjson_prefix(j.front());
8278
                    const bool same_prefix = std::all_of(j.begin(), j.end(),
8279
                                                         [this, first_prefix](const BasicJsonType & v)
8280
                    {
8281
                        return ubjson_prefix(v) == first_prefix;
8282
                    });
8283
8284
                    if (same_prefix)
8285
                    {
8286
                        prefix_required = false;
8287
                        oa->write_character(static_cast<CharType>('$'));
8288
                        oa->write_character(first_prefix);
8289
                    }
8290
                }
8291
8292
                if (use_count)
8293
                {
8294
                    oa->write_character(static_cast<CharType>('#'));
8295
                    write_number_with_ubjson_prefix(j.m_value.object->size(), true);
8296
                }
8297
8298
                for (const auto& el : *j.m_value.object)
8299
                {
8300
                    write_number_with_ubjson_prefix(el.first.size(), true);
8301
                    oa->write_characters(
8302
                        reinterpret_cast<const CharType*>(el.first.c_str()),
8303
                        el.first.size());
8304
                    write_ubjson(el.second, use_count, use_type, prefix_required);
8305
                }
8306
8307
                if (not use_count)
8308
                {
8309
                    oa->write_character(static_cast<CharType>('}'));
8310
                }
8311
8312
                break;
8313
            }
8314
8315
            default:
8316
                break;
8317
        }
8318
    }
8319
8320
  private:
8321
    /*
8322
    @brief write a number to output input
8323
8324
    @param[in] n number of type @a NumberType
8325
    @tparam NumberType the type of the number
8326
8327
    @note This function needs to respect the system's endianess, because bytes
8328
          in CBOR, MessagePack, and UBJSON are stored in network order (big
8329
          endian) and therefore need reordering on little endian systems.
8330
    */
8331
    template<typename NumberType>
8332
    void write_number(const NumberType n)
8333
    {
8334
        // step 1: write number to array of length NumberType
8335
        std::array<CharType, sizeof(NumberType)> vec;
8336
        std::memcpy(vec.data(), &n, sizeof(NumberType));
8337
8338
        // step 2: write array to output (with possible reordering)
8339
        if (is_little_endian)
8340
        {
8341
            // reverse byte order prior to conversion if necessary
8342
            std::reverse(vec.begin(), vec.end());
8343
        }
8344
8345
        oa->write_characters(vec.data(), sizeof(NumberType));
8346
    }
8347
8348
    // UBJSON: write number (floating point)
8349
    template<typename NumberType, typename std::enable_if<
8350
                 std::is_floating_point<NumberType>::value, int>::type = 0>
8351
    void write_number_with_ubjson_prefix(const NumberType n,
8352
                                         const bool add_prefix)
8353
    {
8354
        if (add_prefix)
8355
        {
8356
            oa->write_character(get_ubjson_float_prefix(n));
8357
        }
8358
        write_number(n);
8359
    }
8360
8361
    // UBJSON: write number (unsigned integer)
8362
    template<typename NumberType, typename std::enable_if<
8363
                 std::is_unsigned<NumberType>::value, int>::type = 0>
8364
    void write_number_with_ubjson_prefix(const NumberType n,
8365
                                         const bool add_prefix)
8366
    {
8367
        if (n <= static_cast<uint64_t>((std::numeric_limits<int8_t>::max)()))
8368
        {
8369
            if (add_prefix)
8370
            {
8371
                oa->write_character(static_cast<CharType>('i'));  // int8
8372
            }
8373
            write_number(static_cast<uint8_t>(n));
8374
        }
8375
        else if (n <= (std::numeric_limits<uint8_t>::max)())
8376
        {
8377
            if (add_prefix)
8378
            {
8379
                oa->write_character(static_cast<CharType>('U'));  // uint8
8380
            }
8381
            write_number(static_cast<uint8_t>(n));
8382
        }
8383
        else if (n <= static_cast<uint64_t>((std::numeric_limits<int16_t>::max)()))
8384
        {
8385
            if (add_prefix)
8386
            {
8387
                oa->write_character(static_cast<CharType>('I'));  // int16
8388
            }
8389
            write_number(static_cast<int16_t>(n));
8390
        }
8391
        else if (n <= static_cast<uint64_t>((std::numeric_limits<int32_t>::max)()))
8392
        {
8393
            if (add_prefix)
8394
            {
8395
                oa->write_character(static_cast<CharType>('l'));  // int32
8396
            }
8397
            write_number(static_cast<int32_t>(n));
8398
        }
8399
        else if (n <= static_cast<uint64_t>((std::numeric_limits<int64_t>::max)()))
8400
        {
8401
            if (add_prefix)
8402
            {
8403
                oa->write_character(static_cast<CharType>('L'));  // int64
8404
            }
8405
            write_number(static_cast<int64_t>(n));
8406
        }
8407
        else
8408
        {
8409
            JSON_THROW(out_of_range::create(407, "number overflow serializing " + std::to_string(n)));
8410
        }
8411
    }
8412
8413
    // UBJSON: write number (signed integer)
8414
    template<typename NumberType, typename std::enable_if<
8415
                 std::is_signed<NumberType>::value and
8416
                 not std::is_floating_point<NumberType>::value, int>::type = 0>
8417
    void write_number_with_ubjson_prefix(const NumberType n,
8418
                                         const bool add_prefix)
8419
    {
8420
        if ((std::numeric_limits<int8_t>::min)() <= n and n <= (std::numeric_limits<int8_t>::max)())
8421
        {
8422
            if (add_prefix)
8423
            {
8424
                oa->write_character(static_cast<CharType>('i'));  // int8
8425
            }
8426
            write_number(static_cast<int8_t>(n));
8427
        }
8428
        else if (static_cast<int64_t>((std::numeric_limits<uint8_t>::min)()) <= n and n <= static_cast<int64_t>((std::numeric_limits<uint8_t>::max)()))
8429
        {
8430
            if (add_prefix)
8431
            {
8432
                oa->write_character(static_cast<CharType>('U'));  // uint8
8433
            }
8434
            write_number(static_cast<uint8_t>(n));
8435
        }
8436
        else if ((std::numeric_limits<int16_t>::min)() <= n and n <= (std::numeric_limits<int16_t>::max)())
8437
        {
8438
            if (add_prefix)
8439
            {
8440
                oa->write_character(static_cast<CharType>('I'));  // int16
8441
            }
8442
            write_number(static_cast<int16_t>(n));
8443
        }
8444
        else if ((std::numeric_limits<int32_t>::min)() <= n and n <= (std::numeric_limits<int32_t>::max)())
8445
        {
8446
            if (add_prefix)
8447
            {
8448
                oa->write_character(static_cast<CharType>('l'));  // int32
8449
            }
8450
            write_number(static_cast<int32_t>(n));
8451
        }
8452
        else if ((std::numeric_limits<int64_t>::min)() <= n and n <= (std::numeric_limits<int64_t>::max)())
8453
        {
8454
            if (add_prefix)
8455
            {
8456
                oa->write_character(static_cast<CharType>('L'));  // int64
8457
            }
8458
            write_number(static_cast<int64_t>(n));
8459
        }
8460
        // LCOV_EXCL_START
8461
        else
8462
        {
8463
            JSON_THROW(out_of_range::create(407, "number overflow serializing " + std::to_string(n)));
8464
        }
8465
        // LCOV_EXCL_STOP
8466
    }
8467
8468
    /*!
8469
    @brief determine the type prefix of container values
8470
8471
    @note This function does not need to be 100% accurate when it comes to
8472
          integer limits. In case a number exceeds the limits of int64_t,
8473
          this will be detected by a later call to function
8474
          write_number_with_ubjson_prefix. Therefore, we return 'L' for any
8475
          value that does not fit the previous limits.
8476
    */
8477
    CharType ubjson_prefix(const BasicJsonType& j) const noexcept
8478
    {
8479
        switch (j.type())
8480
        {
8481
            case value_t::null:
8482
                return 'Z';
8483
8484
            case value_t::boolean:
8485
                return j.m_value.boolean ? 'T' : 'F';
8486
8487
            case value_t::number_integer:
8488
            {
8489
                if ((std::numeric_limits<int8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<int8_t>::max)())
8490
                {
8491
                    return 'i';
8492
                }
8493
                else if ((std::numeric_limits<uint8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<uint8_t>::max)())
8494
                {
8495
                    return 'U';
8496
                }
8497
                else if ((std::numeric_limits<int16_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<int16_t>::max)())
8498
                {
8499
                    return 'I';
8500
                }
8501
                else if ((std::numeric_limits<int32_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<int32_t>::max)())
8502
                {
8503
                    return 'l';
8504
                }
8505
                else  // no check and assume int64_t (see note above)
8506
                {
8507
                    return 'L';
8508
                }
8509
            }
8510
8511
            case value_t::number_unsigned:
8512
            {
8513
                if (j.m_value.number_unsigned <= (std::numeric_limits<int8_t>::max)())
8514
                {
8515
                    return 'i';
8516
                }
8517
                else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
8518
                {
8519
                    return 'U';
8520
                }
8521
                else if (j.m_value.number_unsigned <= (std::numeric_limits<int16_t>::max)())
8522
                {
8523
                    return 'I';
8524
                }
8525
                else if (j.m_value.number_unsigned <= (std::numeric_limits<int32_t>::max)())
8526
                {
8527
                    return 'l';
8528
                }
8529
                else  // no check and assume int64_t (see note above)
8530
                {
8531
                    return 'L';
8532
                }
8533
            }
8534
8535
            case value_t::number_float:
8536
                return get_ubjson_float_prefix(j.m_value.number_float);
8537
8538
            case value_t::string:
8539
                return 'S';
8540
8541
            case value_t::array:
8542
                return '[';
8543
8544
            case value_t::object:
8545
                return '{';
8546
8547
            default:  // discarded values
8548
                return 'N';
8549
        }
8550
    }
8551
8552
    static constexpr CharType get_cbor_float_prefix(float)
8553
    {
8554
        return static_cast<CharType>(0xFA);  // Single-Precision Float
8555
    }
8556
8557
    static constexpr CharType get_cbor_float_prefix(double)
8558
    {
8559
        return static_cast<CharType>(0xFB);  // Double-Precision Float
8560
    }
8561
8562
    static constexpr CharType get_msgpack_float_prefix(float)
8563
    {
8564
        return static_cast<CharType>(0xCA);  // float 32
8565
    }
8566
8567
    static constexpr CharType get_msgpack_float_prefix(double)
8568
    {
8569
        return static_cast<CharType>(0xCB);  // float 64
8570
    }
8571
8572
    static constexpr CharType get_ubjson_float_prefix(float)
8573
    {
8574
        return 'd';  // float 32
8575
    }
8576
8577
    static constexpr CharType get_ubjson_float_prefix(double)
8578
    {
8579
        return 'D';  // float 64
8580
    }
8581
8582
  private:
8583
    /// whether we can assume little endianess
8584
    const bool is_little_endian = binary_reader<BasicJsonType>::little_endianess();
8585
8586
    /// the output
8587
    output_adapter_t<CharType> oa = nullptr;
8588
};
8589
}
8590
}
8591
8592
// #include <nlohmann/detail/output/serializer.hpp>
8593
8594
8595
#include <algorithm> // reverse, remove, fill, find, none_of
8596
#include <array> // array
8597
#include <cassert> // assert
8598
#include <ciso646> // and, or
8599
#include <clocale> // localeconv, lconv
8600
#include <cmath> // labs, isfinite, isnan, signbit
8601
#include <cstddef> // size_t, ptrdiff_t
8602
#include <cstdint> // uint8_t
8603
#include <cstdio> // snprintf
8604
#include <limits> // numeric_limits
8605
#include <string> // string
8606
#include <type_traits> // is_same
8607
8608
// #include <nlohmann/detail/exceptions.hpp>
8609
8610
// #include <nlohmann/detail/conversions/to_chars.hpp>
8611
8612
8613
#include <cassert> // assert
8614
#include <ciso646> // or, and, not
8615
#include <cmath>   // signbit, isfinite
8616
#include <cstdint> // intN_t, uintN_t
8617
#include <cstring> // memcpy, memmove
8618
8619
namespace nlohmann
8620
{
8621
namespace detail
8622
{
8623
8624
/*!
8625
@brief implements the Grisu2 algorithm for binary to decimal floating-point
8626
conversion.
8627
8628
This implementation is a slightly modified version of the reference
8629
implementation which may be obtained from
8630
http://florian.loitsch.com/publications (bench.tar.gz).
8631
8632
The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch.
8633
8634
For a detailed description of the algorithm see:
8635
8636
[1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with
8637
    Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming
8638
    Language Design and Implementation, PLDI 2010
8639
[2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately",
8640
    Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language
8641
    Design and Implementation, PLDI 1996
8642
*/
8643
namespace dtoa_impl
8644
{
8645
8646
template <typename Target, typename Source>
8647
Target reinterpret_bits(const Source source)
8648
7
{
8649
7
    static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
8650
7
8651
7
    Target target;
8652
7
    std::memcpy(&target, &source, sizeof(Source));
8653
7
    return target;
8654
7
}
8655
8656
struct diyfp // f * 2^e
8657
{
8658
    static constexpr int kPrecision = 64; // = q
8659
8660
    uint64_t f;
8661
    int e;
8662
8663
0
    constexpr diyfp() noexcept : f(0), e(0) {}
8664
91
    constexpr diyfp(uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
8665
8666
    /*!
8667
    @brief returns x - y
8668
    @pre x.e == y.e and x.f >= y.f
8669
    */
8670
    static diyfp sub(const diyfp& x, const diyfp& y) noexcept
8671
14
    {
8672
14
        assert(x.e == y.e);
8673
14
        assert(x.f >= y.f);
8674
14
8675
14
        return diyfp(x.f - y.f, x.e);
8676
14
    }
8677
8678
    /*!
8679
    @brief returns x * y
8680
    @note The result is rounded. (Only the upper q bits are returned.)
8681
    */
8682
    static diyfp mul(const diyfp& x, const diyfp& y) noexcept
8683
21
    {
8684
21
        static_assert(kPrecision == 64, "internal error");
8685
21
8686
21
        // Computes:
8687
21
        //  f = round((x.f * y.f) / 2^q)
8688
21
        //  e = x.e + y.e + q
8689
21
8690
21
        // Emulate the 64-bit * 64-bit multiplication:
8691
21
        //
8692
21
        // p = u * v
8693
21
        //   = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
8694
21
        //   = (u_lo v_lo         ) + 2^32 ((u_lo v_hi         ) + (u_hi v_lo         )) + 2^64 (u_hi v_hi         )
8695
21
        //   = (p0                ) + 2^32 ((p1                ) + (p2                )) + 2^64 (p3                )
8696
21
        //   = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3                )
8697
21
        //   = (p0_lo             ) + 2^32 (p0_hi + p1_lo + p2_lo                      ) + 2^64 (p1_hi + p2_hi + p3)
8698
21
        //   = (p0_lo             ) + 2^32 (Q                                          ) + 2^64 (H                 )
8699
21
        //   = (p0_lo             ) + 2^32 (Q_lo + 2^32 Q_hi                           ) + 2^64 (H                 )
8700
21
        //
8701
21
        // (Since Q might be larger than 2^32 - 1)
8702
21
        //
8703
21
        //   = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
8704
21
        //
8705
21
        // (Q_hi + H does not overflow a 64-bit int)
8706
21
        //
8707
21
        //   = p_lo + 2^64 p_hi
8708
21
8709
21
        const uint64_t u_lo = x.f & 0xFFFFFFFF;
8710
21
        const uint64_t u_hi = x.f >> 32;
8711
21
        const uint64_t v_lo = y.f & 0xFFFFFFFF;
8712
21
        const uint64_t v_hi = y.f >> 32;
8713
21
8714
21
        const uint64_t p0 = u_lo * v_lo;
8715
21
        const uint64_t p1 = u_lo * v_hi;
8716
21
        const uint64_t p2 = u_hi * v_lo;
8717
21
        const uint64_t p3 = u_hi * v_hi;
8718
21
8719
21
        const uint64_t p0_hi = p0 >> 32;
8720
21
        const uint64_t p1_lo = p1 & 0xFFFFFFFF;
8721
21
        const uint64_t p1_hi = p1 >> 32;
8722
21
        const uint64_t p2_lo = p2 & 0xFFFFFFFF;
8723
21
        const uint64_t p2_hi = p2 >> 32;
8724
21
8725
21
        uint64_t Q = p0_hi + p1_lo + p2_lo;
8726
21
8727
21
        // The full product might now be computed as
8728
21
        //
8729
21
        // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
8730
21
        // p_lo = p0_lo + (Q << 32)
8731
21
        //
8732
21
        // But in this particular case here, the full p_lo is not required.
8733
21
        // Effectively we only need to add the highest bit in p_lo to p_hi (and
8734
21
        // Q_hi + 1 does not overflow).
8735
21
8736
21
        Q += uint64_t{1} << (64 - 32 - 1); // round, ties up
8737
21
8738
21
        const uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32);
8739
21
8740
21
        return diyfp(h, x.e + y.e + 64);
8741
21
    }
8742
8743
    /*!
8744
    @brief normalize x such that the significand is >= 2^(q-1)
8745
    @pre x.f != 0
8746
    */
8747
    static diyfp normalize(diyfp x) noexcept
8748
14
    {
8749
14
        assert(x.f != 0);
8750
14
8751
161
        while ((x.f >> 63) == 0)
8752
147
        {
8753
147
            x.f <<= 1;
8754
147
            x.e--;
8755
147
        }
8756
14
8757
14
        return x;
8758
14
    }
8759
8760
    /*!
8761
    @brief normalize x such that the result has the exponent E
8762
    @pre e >= x.e and the upper e - x.e bits of x.f must be zero.
8763
    */
8764
    static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
8765
7
    {
8766
7
        const int delta = x.e - target_exponent;
8767
7
8768
7
        assert(delta >= 0);
8769
7
        assert(((x.f << delta) >> delta) == x.f);
8770
7
8771
7
        return diyfp(x.f << delta, target_exponent);
8772
7
    }
8773
};
8774
8775
struct boundaries
8776
{
8777
    diyfp w;
8778
    diyfp minus;
8779
    diyfp plus;
8780
};
8781
8782
/*!
8783
Compute the (normalized) diyfp representing the input number 'value' and its
8784
boundaries.
8785
8786
@pre value must be finite and positive
8787
*/
8788
template <typename FloatType>
8789
boundaries compute_boundaries(FloatType value)
8790
7
{
8791
7
    assert(std::isfinite(value));
8792
7
    assert(value > 0);
8793
7
8794
7
    // Convert the IEEE representation into a diyfp.
8795
7
    //
8796
7
    // If v is denormal:
8797
7
    //      value = 0.F * 2^(1 - bias) = (          F) * 2^(1 - bias - (p-1))
8798
7
    // If v is normalized:
8799
7
    //      value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
8800
7
8801
7
    static_assert(std::numeric_limits<FloatType>::is_iec559,
8802
7
                  "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
8803
7
8804
7
    constexpr int      kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
8805
7
    constexpr int      kBias      = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
8806
7
    constexpr int      kMinExp    = 1 - kBias;
8807
7
    constexpr uint64_t kHiddenBit = uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
8808
7
8809
7
    using bits_type = typename std::conditional< kPrecision == 24, uint32_t, uint64_t >::type;
8810
7
8811
7
    const uint64_t bits = reinterpret_bits<bits_type>(value);
8812
7
    const uint64_t E = bits >> (kPrecision - 1);
8813
7
    const uint64_t F = bits & (kHiddenBit - 1);
8814
7
8815
7
    const bool is_denormal = (E == 0);
8816
7
    const diyfp v = is_denormal
8817
7
                    ? diyfp(F, kMinExp)
8818
7
                    : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
8819
7
8820
7
    // Compute the boundaries m- and m+ of the floating-point value
8821
7
    // v = f * 2^e.
8822
7
    //
8823
7
    // Determine v- and v+, the floating-point predecessor and successor if v,
8824
7
    // respectively.
8825
7
    //
8826
7
    //      v- = v - 2^e        if f != 2^(p-1) or e == e_min                (A)
8827
7
    //         = v - 2^(e-1)    if f == 2^(p-1) and e > e_min                (B)
8828
7
    //
8829
7
    //      v+ = v + 2^e
8830
7
    //
8831
7
    // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
8832
7
    // between m- and m+ round to v, regardless of how the input rounding
8833
7
    // algorithm breaks ties.
8834
7
    //
8835
7
    //      ---+-------------+-------------+-------------+-------------+---  (A)
8836
7
    //         v-            m-            v             m+            v+
8837
7
    //
8838
7
    //      -----------------+------+------+-------------+-------------+---  (B)
8839
7
    //                       v-     m-     v             m+            v+
8840
7
8841
7
    const bool lower_boundary_is_closer = (F == 0 and E > 1);
8842
7
    const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
8843
7
    const diyfp m_minus = lower_boundary_is_closer
8844
7
                          ? diyfp(4 * v.f - 1, v.e - 2)  // (B)
8845
7
                          : diyfp(2 * v.f - 1, v.e - 1); // (A)
8846
7
8847
7
    // Determine the normalized w+ = m+.
8848
7
    const diyfp w_plus = diyfp::normalize(m_plus);
8849
7
8850
7
    // Determine w- = m- such that e_(w-) = e_(w+).
8851
7
    const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
8852
7
8853
7
    return {diyfp::normalize(v), w_minus, w_plus};
8854
7
}
8855
8856
// Given normalized diyfp w, Grisu needs to find a (normalized) cached
8857
// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
8858
// within a certain range [alpha, gamma] (Definition 3.2 from [1])
8859
//
8860
//      alpha <= e = e_c + e_w + q <= gamma
8861
//
8862
// or
8863
//
8864
//      f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
8865
//                          <= f_c * f_w * 2^gamma
8866
//
8867
// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
8868
//
8869
//      2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
8870
//
8871
// or
8872
//
8873
//      2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
8874
//
8875
// The choice of (alpha,gamma) determines the size of the table and the form of
8876
// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
8877
// in practice:
8878
//
8879
// The idea is to cut the number c * w = f * 2^e into two parts, which can be
8880
// processed independently: An integral part p1, and a fractional part p2:
8881
//
8882
//      f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
8883
//              = (f div 2^-e) + (f mod 2^-e) * 2^e
8884
//              = p1 + p2 * 2^e
8885
//
8886
// The conversion of p1 into decimal form requires a series of divisions and
8887
// modulos by (a power of) 10. These operations are faster for 32-bit than for
8888
// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
8889
// achieved by choosing
8890
//
8891
//      -e >= 32   or   e <= -32 := gamma
8892
//
8893
// In order to convert the fractional part
8894
//
8895
//      p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
8896
//
8897
// into decimal form, the fraction is repeatedly multiplied by 10 and the digits
8898
// d[-i] are extracted in order:
8899
//
8900
//      (10 * p2) div 2^-e = d[-1]
8901
//      (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
8902
//
8903
// The multiplication by 10 must not overflow. It is sufficient to choose
8904
//
8905
//      10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
8906
//
8907
// Since p2 = f mod 2^-e < 2^-e,
8908
//
8909
//      -e <= 60   or   e >= -60 := alpha
8910
8911
constexpr int kAlpha = -60;
8912
constexpr int kGamma = -32;
8913
8914
struct cached_power // c = f * 2^e ~= 10^k
8915
{
8916
    uint64_t f;
8917
    int e;
8918
    int k;
8919
};
8920
8921
/*!
8922
For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached
8923
power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c
8924
satisfies (Definition 3.2 from [1])
8925
8926
     alpha <= e_c + e + q <= gamma.
8927
*/
8928
inline cached_power get_cached_power_for_binary_exponent(int e)
8929
7
{
8930
7
    // Now
8931
7
    //
8932
7
    //      alpha <= e_c + e + q <= gamma                                    (1)
8933
7
    //      ==> f_c * 2^alpha <= c * 2^e * 2^q
8934
7
    //
8935
7
    // and since the c's are normalized, 2^(q-1) <= f_c,
8936
7
    //
8937
7
    //      ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
8938
7
    //      ==> 2^(alpha - e - 1) <= c
8939
7
    //
8940
7
    // If c were an exakt power of ten, i.e. c = 10^k, one may determine k as
8941
7
    //
8942
7
    //      k = ceil( log_10( 2^(alpha - e - 1) ) )
8943
7
    //        = ceil( (alpha - e - 1) * log_10(2) )
8944
7
    //
8945
7
    // From the paper:
8946
7
    // "In theory the result of the procedure could be wrong since c is rounded,
8947
7
    //  and the computation itself is approximated [...]. In practice, however,
8948
7
    //  this simple function is sufficient."
8949
7
    //
8950
7
    // For IEEE double precision floating-point numbers converted into
8951
7
    // normalized diyfp's w = f * 2^e, with q = 64,
8952
7
    //
8953
7
    //      e >= -1022      (min IEEE exponent)
8954
7
    //           -52        (p - 1)
8955
7
    //           -52        (p - 1, possibly normalize denormal IEEE numbers)
8956
7
    //           -11        (normalize the diyfp)
8957
7
    //         = -1137
8958
7
    //
8959
7
    // and
8960
7
    //
8961
7
    //      e <= +1023      (max IEEE exponent)
8962
7
    //           -52        (p - 1)
8963
7
    //           -11        (normalize the diyfp)
8964
7
    //         = 960
8965
7
    //
8966
7
    // This binary exponent range [-1137,960] results in a decimal exponent
8967
7
    // range [-307,324]. One does not need to store a cached power for each
8968
7
    // k in this range. For each such k it suffices to find a cached power
8969
7
    // such that the exponent of the product lies in [alpha,gamma].
8970
7
    // This implies that the difference of the decimal exponents of adjacent
8971
7
    // table entries must be less than or equal to
8972
7
    //
8973
7
    //      floor( (gamma - alpha) * log_10(2) ) = 8.
8974
7
    //
8975
7
    // (A smaller distance gamma-alpha would require a larger table.)
8976
7
8977
7
    // NB:
8978
7
    // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
8979
7
8980
7
    constexpr int kCachedPowersSize = 79;
8981
7
    constexpr int kCachedPowersMinDecExp = -300;
8982
7
    constexpr int kCachedPowersDecStep = 8;
8983
7
8984
7
    static constexpr cached_power kCachedPowers[] =
8985
7
    {
8986
7
        { 0xAB70FE17C79AC6CA, -1060, -300 },
8987
7
        { 0xFF77B1FCBEBCDC4F, -1034, -292 },
8988
7
        { 0xBE5691EF416BD60C, -1007, -284 },
8989
7
        { 0x8DD01FAD907FFC3C,  -980, -276 },
8990
7
        { 0xD3515C2831559A83,  -954, -268 },
8991
7
        { 0x9D71AC8FADA6C9B5,  -927, -260 },
8992
7
        { 0xEA9C227723EE8BCB,  -901, -252 },
8993
7
        { 0xAECC49914078536D,  -874, -244 },
8994
7
        { 0x823C12795DB6CE57,  -847, -236 },
8995
7
        { 0xC21094364DFB5637,  -821, -228 },
8996
7
        { 0x9096EA6F3848984F,  -794, -220 },
8997
7
        { 0xD77485CB25823AC7,  -768, -212 },
8998
7
        { 0xA086CFCD97BF97F4,  -741, -204 },
8999
7
        { 0xEF340A98172AACE5,  -715, -196 },
9000
7
        { 0xB23867FB2A35B28E,  -688, -188 },
9001
7
        { 0x84C8D4DFD2C63F3B,  -661, -180 },
9002
7
        { 0xC5DD44271AD3CDBA,  -635, -172 },
9003
7
        { 0x936B9FCEBB25C996,  -608, -164 },
9004
7
        { 0xDBAC6C247D62A584,  -582, -156 },
9005
7
        { 0xA3AB66580D5FDAF6,  -555, -148 },
9006
7
        { 0xF3E2F893DEC3F126,  -529, -140 },
9007
7
        { 0xB5B5ADA8AAFF80B8,  -502, -132 },
9008
7
        { 0x87625F056C7C4A8B,  -475, -124 },
9009
7
        { 0xC9BCFF6034C13053,  -449, -116 },
9010
7
        { 0x964E858C91BA2655,  -422, -108 },
9011
7
        { 0xDFF9772470297EBD,  -396, -100 },
9012
7
        { 0xA6DFBD9FB8E5B88F,  -369,  -92 },
9013
7
        { 0xF8A95FCF88747D94,  -343,  -84 },
9014
7
        { 0xB94470938FA89BCF,  -316,  -76 },
9015
7
        { 0x8A08F0F8BF0F156B,  -289,  -68 },
9016
7
        { 0xCDB02555653131B6,  -263,  -60 },
9017
7
        { 0x993FE2C6D07B7FAC,  -236,  -52 },
9018
7
        { 0xE45C10C42A2B3B06,  -210,  -44 },
9019
7
        { 0xAA242499697392D3,  -183,  -36 },
9020
7
        { 0xFD87B5F28300CA0E,  -157,  -28 },
9021
7
        { 0xBCE5086492111AEB,  -130,  -20 },
9022
7
        { 0x8CBCCC096F5088CC,  -103,  -12 },
9023
7
        { 0xD1B71758E219652C,   -77,   -4 },
9024
7
        { 0x9C40000000000000,   -50,    4 },
9025
7
        { 0xE8D4A51000000000,   -24,   12 },
9026
7
        { 0xAD78EBC5AC620000,     3,   20 },
9027
7
        { 0x813F3978F8940984,    30,   28 },
9028
7
        { 0xC097CE7BC90715B3,    56,   36 },
9029
7
        { 0x8F7E32CE7BEA5C70,    83,   44 },
9030
7
        { 0xD5D238A4ABE98068,   109,   52 },
9031
7
        { 0x9F4F2726179A2245,   136,   60 },
9032
7
        { 0xED63A231D4C4FB27,   162,   68 },
9033
7
        { 0xB0DE65388CC8ADA8,   189,   76 },
9034
7
        { 0x83C7088E1AAB65DB,   216,   84 },
9035
7
        { 0xC45D1DF942711D9A,   242,   92 },
9036
7
        { 0x924D692CA61BE758,   269,  100 },
9037
7
        { 0xDA01EE641A708DEA,   295,  108 },
9038
7
        { 0xA26DA3999AEF774A,   322,  116 },
9039
7
        { 0xF209787BB47D6B85,   348,  124 },
9040
7
        { 0xB454E4A179DD1877,   375,  132 },
9041
7
        { 0x865B86925B9BC5C2,   402,  140 },
9042
7
        { 0xC83553C5C8965D3D,   428,  148 },
9043
7
        { 0x952AB45CFA97A0B3,   455,  156 },
9044
7
        { 0xDE469FBD99A05FE3,   481,  164 },
9045
7
        { 0xA59BC234DB398C25,   508,  172 },
9046
7
        { 0xF6C69A72A3989F5C,   534,  180 },
9047
7
        { 0xB7DCBF5354E9BECE,   561,  188 },
9048
7
        { 0x88FCF317F22241E2,   588,  196 },
9049
7
        { 0xCC20CE9BD35C78A5,   614,  204 },
9050
7
        { 0x98165AF37B2153DF,   641,  212 },
9051
7
        { 0xE2A0B5DC971F303A,   667,  220 },
9052
7
        { 0xA8D9D1535CE3B396,   694,  228 },
9053
7
        { 0xFB9B7CD9A4A7443C,   720,  236 },
9054
7
        { 0xBB764C4CA7A44410,   747,  244 },
9055
7
        { 0x8BAB8EEFB6409C1A,   774,  252 },
9056
7
        { 0xD01FEF10A657842C,   800,  260 },
9057
7
        { 0x9B10A4E5E9913129,   827,  268 },
9058
7
        { 0xE7109BFBA19C0C9D,   853,  276 },
9059
7
        { 0xAC2820D9623BF429,   880,  284 },
9060
7
        { 0x80444B5E7AA7CF85,   907,  292 },
9061
7
        { 0xBF21E44003ACDD2D,   933,  300 },
9062
7
        { 0x8E679C2F5E44FF8F,   960,  308 },
9063
7
        { 0xD433179D9C8CB841,   986,  316 },
9064
7
        { 0x9E19DB92B4E31BA9,  1013,  324 },
9065
7
    };
9066
7
9067
7
    // This computation gives exactly the same results for k as
9068
7
    //      k = ceil((kAlpha - e - 1) * 0.30102999566398114)
9069
7
    // for |e| <= 1500, but doesn't require floating-point operations.
9070
7
    // NB: log_10(2) ~= 78913 / 2^18
9071
7
    assert(e >= -1500);
9072
7
    assert(e <=  1500);
9073
7
    const int f = kAlpha - e - 1;
9074
7
    const int k = (f * 78913) / (1 << 18) + (f > 0);
9075
7
9076
7
    const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
9077
7
    assert(index >= 0);
9078
7
    assert(index < kCachedPowersSize);
9079
7
    static_cast<void>(kCachedPowersSize); // Fix warning.
9080
7
9081
7
    const cached_power cached = kCachedPowers[index];
9082
7
    assert(kAlpha <= cached.e + e + 64);
9083
7
    assert(kGamma >= cached.e + e + 64);
9084
7
9085
7
    return cached;
9086
7
}
9087
9088
/*!
9089
For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k.
9090
For n == 0, returns 1 and sets pow10 := 1.
9091
*/
9092
inline int find_largest_pow10(const uint32_t n, uint32_t& pow10)
9093
7
{
9094
7
    // LCOV_EXCL_START
9095
7
    if (n >= 1000000000)
9096
0
    {
9097
0
        pow10 = 1000000000;
9098
0
        return 10;
9099
0
    }
9100
7
    // LCOV_EXCL_STOP
9101
7
    else if (n >= 100000000)
9102
0
    {
9103
0
        pow10 = 100000000;
9104
0
        return  9;
9105
0
    }
9106
7
    else if (n >= 10000000)
9107
0
    {
9108
0
        pow10 = 10000000;
9109
0
        return  8;
9110
0
    }
9111
7
    else if (n >= 1000000)
9112
0
    {
9113
0
        pow10 = 1000000;
9114
0
        return  7;
9115
0
    }
9116
7
    else if (n >= 100000)
9117
6
    {
9118
6
        pow10 = 100000;
9119
6
        return  6;
9120
6
    }
9121
1
    else if (n >= 10000)
9122
1
    {
9123
1
        pow10 = 10000;
9124
1
        return  5;
9125
1
    }
9126
0
    else if (n >= 1000)
9127
0
    {
9128
0
        pow10 = 1000;
9129
0
        return  4;
9130
0
    }
9131
0
    else if (n >= 100)
9132
0
    {
9133
0
        pow10 = 100;
9134
0
        return  3;
9135
0
    }
9136
0
    else if (n >= 10)
9137
0
    {
9138
0
        pow10 = 10;
9139
0
        return  2;
9140
0
    }
9141
0
    else
9142
0
    {
9143
0
        pow10 = 1;
9144
0
        return 1;
9145
0
    }
9146
0
}
9147
9148
inline void grisu2_round(char* buf, int len, uint64_t dist, uint64_t delta,
9149
                         uint64_t rest, uint64_t ten_k)
9150
7
{
9151
7
    assert(len >= 1);
9152
7
    assert(dist <= delta);
9153
7
    assert(rest <= delta);
9154
7
    assert(ten_k > 0);
9155
7
9156
7
    //               <--------------------------- delta ---->
9157
7
    //                                  <---- dist --------->
9158
7
    // --------------[------------------+-------------------]--------------
9159
7
    //               M-                 w                   M+
9160
7
    //
9161
7
    //                                  ten_k
9162
7
    //                                <------>
9163
7
    //                                       <---- rest ---->
9164
7
    // --------------[------------------+----+--------------]--------------
9165
7
    //                                  w    V
9166
7
    //                                       = buf * 10^k
9167
7
    //
9168
7
    // ten_k represents a unit-in-the-last-place in the decimal representation
9169
7
    // stored in buf.
9170
7
    // Decrement buf by ten_k while this takes buf closer to w.
9171
7
9172
7
    // The tests are written in this order to avoid overflow in unsigned
9173
7
    // integer arithmetic.
9174
7
9175
7
    while (rest < dist
9176
7
            and delta - rest >= ten_k
9177
7
            and (rest + ten_k < dist or dist - rest > rest + ten_k - dist))
9178
0
    {
9179
0
        assert(buf[len - 1] != '0');
9180
0
        buf[len - 1]--;
9181
0
        rest += ten_k;
9182
0
    }
9183
7
}
9184
9185
/*!
9186
Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+.
9187
M- and M+ must be normalized and share the same exponent -60 <= e <= -32.
9188
*/
9189
inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
9190
                             diyfp M_minus, diyfp w, diyfp M_plus)
9191
7
{
9192
7
    static_assert(kAlpha >= -60, "internal error");
9193
7
    static_assert(kGamma <= -32, "internal error");
9194
7
9195
7
    // Generates the digits (and the exponent) of a decimal floating-point
9196
7
    // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
9197
7
    // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
9198
7
    //
9199
7
    //               <--------------------------- delta ---->
9200
7
    //                                  <---- dist --------->
9201
7
    // --------------[------------------+-------------------]--------------
9202
7
    //               M-                 w                   M+
9203
7
    //
9204
7
    // Grisu2 generates the digits of M+ from left to right and stops as soon as
9205
7
    // V is in [M-,M+].
9206
7
9207
7
    assert(M_plus.e >= kAlpha);
9208
7
    assert(M_plus.e <= kGamma);
9209
7
9210
7
    uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
9211
7
    uint64_t dist  = diyfp::sub(M_plus, w      ).f; // (significand of (M+ - w ), implicit exponent is e)
9212
7
9213
7
    // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
9214
7
    //
9215
7
    //      M+ = f * 2^e
9216
7
    //         = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
9217
7
    //         = ((p1        ) * 2^-e + (p2        )) * 2^e
9218
7
    //         = p1 + p2 * 2^e
9219
7
9220
7
    const diyfp one(uint64_t{1} << -M_plus.e, M_plus.e);
9221
7
9222
7
    uint32_t p1 = static_cast<uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
9223
7
    uint64_t p2 = M_plus.f & (one.f - 1);                    // p2 = f mod 2^-e
9224
7
9225
7
    // 1)
9226
7
    //
9227
7
    // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
9228
7
9229
7
    assert(p1 > 0);
9230
7
9231
7
    uint32_t pow10;
9232
7
    const int k = find_largest_pow10(p1, pow10);
9233
7
9234
7
    //      10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
9235
7
    //
9236
7
    //      p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
9237
7
    //         = (d[k-1]         ) * 10^(k-1) + (p1 mod 10^(k-1))
9238
7
    //
9239
7
    //      M+ = p1                                             + p2 * 2^e
9240
7
    //         = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1))          + p2 * 2^e
9241
7
    //         = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
9242
7
    //         = d[k-1] * 10^(k-1) + (                         rest) * 2^e
9243
7
    //
9244
7
    // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
9245
7
    //
9246
7
    //      p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
9247
7
    //
9248
7
    // but stop as soon as
9249
7
    //
9250
7
    //      rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
9251
7
9252
7
    int n = k;
9253
41
    while (n > 0)
9254
37
    {
9255
37
        // Invariants:
9256
37
        //      M+ = buffer * 10^n + (p1 + p2 * 2^e)    (buffer = 0 for n = k)
9257
37
        //      pow10 = 10^(n-1) <= p1 < 10^n
9258
37
        //
9259
37
        const uint32_t d = p1 / pow10;  // d = p1 div 10^(n-1)
9260
37
        const uint32_t r = p1 % pow10;  // r = p1 mod 10^(n-1)
9261
37
        //
9262
37
        //      M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
9263
37
        //         = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
9264
37
        //
9265
37
        assert(d <= 9);
9266
37
        buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
9267
37
        //
9268
37
        //      M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
9269
37
        //
9270
37
        p1 = r;
9271
37
        n--;
9272
37
        //
9273
37
        //      M+ = buffer * 10^n + (p1 + p2 * 2^e)
9274
37
        //      pow10 = 10^n
9275
37
        //
9276
37
9277
37
        // Now check if enough digits have been generated.
9278
37
        // Compute
9279
37
        //
9280
37
        //      p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
9281
37
        //
9282
37
        // Note:
9283
37
        // Since rest and delta share the same exponent e, it suffices to
9284
37
        // compare the significands.
9285
37
        const uint64_t rest = (uint64_t{p1} << -one.e) + p2;
9286
37
        if (rest <= delta)
9287
3
        {
9288
3
            // V = buffer * 10^n, with M- <= V <= M+.
9289
3
9290
3
            decimal_exponent += n;
9291
3
9292
3
            // We may now just stop. But instead look if the buffer could be
9293
3
            // decremented to bring V closer to w.
9294
3
            //
9295
3
            // pow10 = 10^n is now 1 ulp in the decimal representation V.
9296
3
            // The rounding procedure works with diyfp's with an implicit
9297
3
            // exponent of e.
9298
3
            //
9299
3
            //      10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
9300
3
            //
9301
3
            const uint64_t ten_n = uint64_t{pow10} << -one.e;
9302
3
            grisu2_round(buffer, length, dist, delta, rest, ten_n);
9303
3
9304
3
            return;
9305
3
        }
9306
34
9307
34
        pow10 /= 10;
9308
34
        //
9309
34
        //      pow10 = 10^(n-1) <= p1 < 10^n
9310
34
        // Invariants restored.
9311
34
    }
9312
7
9313
7
    // 2)
9314
7
    //
9315
7
    // The digits of the integral part have been generated:
9316
7
    //
9317
7
    //      M+ = d[k-1]...d[1]d[0] + p2 * 2^e
9318
7
    //         = buffer            + p2 * 2^e
9319
7
    //
9320
7
    // Now generate the digits of the fractional part p2 * 2^e.
9321
7
    //
9322
7
    // Note:
9323
7
    // No decimal point is generated: the exponent is adjusted instead.
9324
7
    //
9325
7
    // p2 actually represents the fraction
9326
7
    //
9327
7
    //      p2 * 2^e
9328
7
    //          = p2 / 2^-e
9329
7
    //          = d[-1] / 10^1 + d[-2] / 10^2 + ...
9330
7
    //
9331
7
    // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
9332
7
    //
9333
7
    //      p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
9334
7
    //                      + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
9335
7
    //
9336
7
    // using
9337
7
    //
9338
7
    //      10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
9339
7
    //                = (                   d) * 2^-e + (                   r)
9340
7
    //
9341
7
    // or
9342
7
    //      10^m * p2 * 2^e = d + r * 2^e
9343
7
    //
9344
7
    // i.e.
9345
7
    //
9346
7
    //      M+ = buffer + p2 * 2^e
9347
7
    //         = buffer + 10^-m * (d + r * 2^e)
9348
7
    //         = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
9349
7
    //
9350
7
    // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
9351
7
9352
7
    assert(p2 > delta);
9353
4
9354
4
    int m = 0;
9355
4
    for (;;)
9356
4
    {
9357
4
        // Invariant:
9358
4
        //      M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
9359
4
        //         = buffer * 10^-m + 10^-m * (p2                                 ) * 2^e
9360
4
        //         = buffer * 10^-m + 10^-m * (1/10 * (10 * p2)                   ) * 2^e
9361
4
        //         = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
9362
4
        //
9363
4
        assert(p2 <= UINT64_MAX / 10);
9364
4
        p2 *= 10;
9365
4
        const uint64_t d = p2 >> -one.e;     // d = (10 * p2) div 2^-e
9366
4
        const uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
9367
4
        //
9368
4
        //      M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
9369
4
        //         = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
9370
4
        //         = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
9371
4
        //
9372
4
        assert(d <= 9);
9373
4
        buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
9374
4
        //
9375
4
        //      M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
9376
4
        //
9377
4
        p2 = r;
9378
4
        m++;
9379
4
        //
9380
4
        //      M+ = buffer * 10^-m + 10^-m * p2 * 2^e
9381
4
        // Invariant restored.
9382
4
9383
4
        // Check if enough digits have been generated.
9384
4
        //
9385
4
        //      10^-m * p2 * 2^e <= delta * 2^e
9386
4
        //              p2 * 2^e <= 10^m * delta * 2^e
9387
4
        //                    p2 <= 10^m * delta
9388
4
        delta *= 10;
9389
4
        dist  *= 10;
9390
4
        if (p2 <= delta)
9391
4
        {
9392
4
            break;
9393
4
        }
9394
4
    }
9395
4
9396
4
    // V = buffer * 10^-m, with M- <= V <= M+.
9397
4
9398
4
    decimal_exponent -= m;
9399
4
9400
4
    // 1 ulp in the decimal representation is now 10^-m.
9401
4
    // Since delta and dist are now scaled by 10^m, we need to do the
9402
4
    // same with ulp in order to keep the units in sync.
9403
4
    //
9404
4
    //      10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
9405
4
    //
9406
4
    const uint64_t ten_m = one.f;
9407
4
    grisu2_round(buffer, length, dist, delta, p2, ten_m);
9408
4
9409
4
    // By construction this algorithm generates the shortest possible decimal
9410
4
    // number (Loitsch, Theorem 6.2) which rounds back to w.
9411
4
    // For an input number of precision p, at least
9412
4
    //
9413
4
    //      N = 1 + ceil(p * log_10(2))
9414
4
    //
9415
4
    // decimal digits are sufficient to identify all binary floating-point
9416
4
    // numbers (Matula, "In-and-Out conversions").
9417
4
    // This implies that the algorithm does not produce more than N decimal
9418
4
    // digits.
9419
4
    //
9420
4
    //      N = 17 for p = 53 (IEEE double precision)
9421
4
    //      N = 9  for p = 24 (IEEE single precision)
9422
4
}
9423
9424
/*!
9425
v = buf * 10^decimal_exponent
9426
len is the length of the buffer (number of decimal digits)
9427
The buffer must be large enough, i.e. >= max_digits10.
9428
*/
9429
inline void grisu2(char* buf, int& len, int& decimal_exponent,
9430
                   diyfp m_minus, diyfp v, diyfp m_plus)
9431
7
{
9432
7
    assert(m_plus.e == m_minus.e);
9433
7
    assert(m_plus.e == v.e);
9434
7
9435
7
    //  --------(-----------------------+-----------------------)--------    (A)
9436
7
    //          m-                      v                       m+
9437
7
    //
9438
7
    //  --------------------(-----------+-----------------------)--------    (B)
9439
7
    //                      m-          v                       m+
9440
7
    //
9441
7
    // First scale v (and m- and m+) such that the exponent is in the range
9442
7
    // [alpha, gamma].
9443
7
9444
7
    const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
9445
7
9446
7
    const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
9447
7
9448
7
    // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
9449
7
    const diyfp w       = diyfp::mul(v,       c_minus_k);
9450
7
    const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
9451
7
    const diyfp w_plus  = diyfp::mul(m_plus,  c_minus_k);
9452
7
9453
7
    //  ----(---+---)---------------(---+---)---------------(---+---)----
9454
7
    //          w-                      w                       w+
9455
7
    //          = c*m-                  = c*v                   = c*m+
9456
7
    //
9457
7
    // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
9458
7
    // w+ are now off by a small amount.
9459
7
    // In fact:
9460
7
    //
9461
7
    //      w - v * 10^k < 1 ulp
9462
7
    //
9463
7
    // To account for this inaccuracy, add resp. subtract 1 ulp.
9464
7
    //
9465
7
    //  --------+---[---------------(---+---)---------------]---+--------
9466
7
    //          w-  M-                  w                   M+  w+
9467
7
    //
9468
7
    // Now any number in [M-, M+] (bounds included) will round to w when input,
9469
7
    // regardless of how the input rounding algorithm breaks ties.
9470
7
    //
9471
7
    // And digit_gen generates the shortest possible such number in [M-, M+].
9472
7
    // Note that this does not mean that Grisu2 always generates the shortest
9473
7
    // possible number in the interval (m-, m+).
9474
7
    const diyfp M_minus(w_minus.f + 1, w_minus.e);
9475
7
    const diyfp M_plus (w_plus.f  - 1, w_plus.e );
9476
7
9477
7
    decimal_exponent = -cached.k; // = -(-k) = k
9478
7
9479
7
    grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
9480
7
}
9481
9482
/*!
9483
v = buf * 10^decimal_exponent
9484
len is the length of the buffer (number of decimal digits)
9485
The buffer must be large enough, i.e. >= max_digits10.
9486
*/
9487
template <typename FloatType>
9488
void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
9489
7
{
9490
7
    static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
9491
7
                  "internal error: not enough precision");
9492
7
9493
7
    assert(std::isfinite(value));
9494
7
    assert(value > 0);
9495
7
9496
7
    // If the neighbors (and boundaries) of 'value' are always computed for double-precision
9497
7
    // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
9498
7
    // decimal representations are not exactly "short".
9499
7
    //
9500
7
    // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
9501
7
    // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
9502
7
    // and since sprintf promotes float's to double's, I think this is exactly what 'std::to_chars'
9503
7
    // does.
9504
7
    // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
9505
7
    // representation using the corresponding std::from_chars function recovers value exactly". That
9506
7
    // indicates that single precision floating-point numbers should be recovered using
9507
7
    // 'std::strtof'.
9508
7
    //
9509
7
    // NB: If the neighbors are computed for single-precision numbers, there is a single float
9510
7
    //     (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
9511
7
    //     value is off by 1 ulp.
9512
#if 0
9513
    const boundaries w = compute_boundaries(static_cast<double>(value));
9514
#else
9515
    const boundaries w = compute_boundaries(value);
9516
7
#endif
9517
7
9518
7
    grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
9519
7
}
9520
9521
/*!
9522
@brief appends a decimal representation of e to buf
9523
@return a pointer to the element following the exponent.
9524
@pre -1000 < e < 1000
9525
*/
9526
inline char* append_exponent(char* buf, int e)
9527
0
{
9528
0
    assert(e > -1000);
9529
0
    assert(e <  1000);
9530
0
9531
0
    if (e < 0)
9532
0
    {
9533
0
        e = -e;
9534
0
        *buf++ = '-';
9535
0
    }
9536
0
    else
9537
0
    {
9538
0
        *buf++ = '+';
9539
0
    }
9540
0
9541
0
    uint32_t k = static_cast<uint32_t>(e);
9542
0
    if (k < 10)
9543
0
    {
9544
0
        // Always print at least two digits in the exponent.
9545
0
        // This is for compatibility with printf("%g").
9546
0
        *buf++ = '0';
9547
0
        *buf++ = static_cast<char>('0' + k);
9548
0
    }
9549
0
    else if (k < 100)
9550
0
    {
9551
0
        *buf++ = static_cast<char>('0' + k / 10);
9552
0
        k %= 10;
9553
0
        *buf++ = static_cast<char>('0' + k);
9554
0
    }
9555
0
    else
9556
0
    {
9557
0
        *buf++ = static_cast<char>('0' + k / 100);
9558
0
        k %= 100;
9559
0
        *buf++ = static_cast<char>('0' + k / 10);
9560
0
        k %= 10;
9561
0
        *buf++ = static_cast<char>('0' + k);
9562
0
    }
9563
0
9564
0
    return buf;
9565
0
}
9566
9567
/*!
9568
@brief prettify v = buf * 10^decimal_exponent
9569
9570
If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point
9571
notation. Otherwise it will be printed in exponential notation.
9572
9573
@pre min_exp < 0
9574
@pre max_exp > 0
9575
*/
9576
inline char* format_buffer(char* buf, int len, int decimal_exponent,
9577
                           int min_exp, int max_exp)
9578
7
{
9579
7
    assert(min_exp < 0);
9580
7
    assert(max_exp > 0);
9581
7
9582
7
    const int k = len;
9583
7
    const int n = len + decimal_exponent;
9584
7
9585
7
    // v = buf * 10^(n-k)
9586
7
    // k is the length of the buffer (number of decimal digits)
9587
7
    // n is the position of the decimal point relative to the start of the buffer.
9588
7
9589
7
    if (k <= n and n <= max_exp)
9590
0
    {
9591
0
        // digits[000]
9592
0
        // len <= max_exp + 2
9593
0
9594
0
        std::memset(buf + k, '0', static_cast<size_t>(n - k));
9595
0
        // Make it look like a floating-point number (#362, #378)
9596
0
        buf[n + 0] = '.';
9597
0
        buf[n + 1] = '0';
9598
0
        return buf + (n + 2);
9599
0
    }
9600
7
9601
7
    if (0 < n and n <= max_exp)
9602
7
    {
9603
7
        // dig.its
9604
7
        // len <= max_digits10 + 1
9605
7
9606
7
        assert(k > n);
9607
7
9608
7
        std::memmove(buf + (n + 1), buf + n, static_cast<size_t>(k - n));
9609
7
        buf[n] = '.';
9610
7
        return buf + (k + 1);
9611
7
    }
9612
0
9613
0
    if (min_exp < n and n <= 0)
9614
0
    {
9615
0
        // 0.[000]digits
9616
0
        // len <= 2 + (-min_exp - 1) + max_digits10
9617
0
9618
0
        std::memmove(buf + (2 + -n), buf, static_cast<size_t>(k));
9619
0
        buf[0] = '0';
9620
0
        buf[1] = '.';
9621
0
        std::memset(buf + 2, '0', static_cast<size_t>(-n));
9622
0
        return buf + (2 + (-n) + k);
9623
0
    }
9624
0
9625
0
    if (k == 1)
9626
0
    {
9627
0
        // dE+123
9628
0
        // len <= 1 + 5
9629
0
9630
0
        buf += 1;
9631
0
    }
9632
0
    else
9633
0
    {
9634
0
        // d.igitsE+123
9635
0
        // len <= max_digits10 + 1 + 5
9636
0
9637
0
        std::memmove(buf + 2, buf + 1, static_cast<size_t>(k - 1));
9638
0
        buf[1] = '.';
9639
0
        buf += 1 + k;
9640
0
    }
9641
0
9642
0
    *buf++ = 'e';
9643
0
    return append_exponent(buf, n - 1);
9644
0
}
9645
9646
} // namespace dtoa_impl
9647
9648
/*!
9649
@brief generates a decimal representation of the floating-point number value in [first, last).
9650
9651
The format of the resulting decimal representation is similar to printf's %g
9652
format. Returns an iterator pointing past-the-end of the decimal representation.
9653
9654
@note The input number must be finite, i.e. NaN's and Inf's are not supported.
9655
@note The buffer must be large enough.
9656
@note The result is NOT null-terminated.
9657
*/
9658
template <typename FloatType>
9659
char* to_chars(char* first, char* last, FloatType value)
9660
7
{
9661
7
    static_cast<void>(last); // maybe unused - fix warning
9662
7
    assert(std::isfinite(value));
9663
7
9664
7
    // Use signbit(value) instead of (value < 0) since signbit works for -0.
9665
7
    if (std::signbit(value))
9666
0
    {
9667
0
        value = -value;
9668
0
        *first++ = '-';
9669
0
    }
9670
7
9671
7
    if (value == 0) // +-0
9672
0
    {
9673
0
        *first++ = '0';
9674
0
        // Make it look like a floating-point number (#362, #378)
9675
0
        *first++ = '.';
9676
0
        *first++ = '0';
9677
0
        return first;
9678
0
    }
9679
7
9680
7
    assert(last - first >= std::numeric_limits<FloatType>::max_digits10);
9681
7
9682
7
    // Compute v = buffer * 10^decimal_exponent.
9683
7
    // The decimal digits are stored in the buffer, which needs to be interpreted
9684
7
    // as an unsigned decimal integer.
9685
7
    // len is the length of the buffer, i.e. the number of decimal digits.
9686
7
    int len = 0;
9687
7
    int decimal_exponent = 0;
9688
7
    dtoa_impl::grisu2(first, len, decimal_exponent, value);
9689
7
9690
7
    assert(len <= std::numeric_limits<FloatType>::max_digits10);
9691
7
9692
7
    // Format the buffer like printf("%.*g", prec, value)
9693
7
    constexpr int kMinExp = -4;
9694
7
    // Use digits10 here to increase compatibility with version 2.
9695
7
    constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
9696
7
9697
7
    assert(last - first >= kMaxExp + 2);
9698
7
    assert(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
9699
7
    assert(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
9700
7
9701
7
    return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
9702
7
}
9703
9704
} // namespace detail
9705
} // namespace nlohmann
9706
9707
// #include <nlohmann/detail/macro_scope.hpp>
9708
9709
// #include <nlohmann/detail/meta/cpp_future.hpp>
9710
9711
// #include <nlohmann/detail/output/output_adapters.hpp>
9712
9713
// #include <nlohmann/detail/value_t.hpp>
9714
9715
9716
namespace nlohmann
9717
{
9718
namespace detail
9719
{
9720
///////////////////
9721
// serialization //
9722
///////////////////
9723
9724
template<typename BasicJsonType>
9725
class serializer
9726
{
9727
    using string_t = typename BasicJsonType::string_t;
9728
    using number_float_t = typename BasicJsonType::number_float_t;
9729
    using number_integer_t = typename BasicJsonType::number_integer_t;
9730
    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9731
    static constexpr uint8_t UTF8_ACCEPT = 0;
9732
    static constexpr uint8_t UTF8_REJECT = 1;
9733
9734
  public:
9735
    /*!
9736
    @param[in] s  output stream to serialize to
9737
    @param[in] ichar  indentation character to use
9738
    */
9739
    serializer(output_adapter_t<char> s, const char ichar)
9740
        : o(std::move(s)), loc(std::localeconv()),
9741
          thousands_sep(loc->thousands_sep == nullptr ? '\0' : * (loc->thousands_sep)),
9742
          decimal_point(loc->decimal_point == nullptr ? '\0' : * (loc->decimal_point)),
9743
          indent_char(ichar), indent_string(512, indent_char)
9744
122
    {}
9745
9746
    // delete because of pointer members
9747
    serializer(const serializer&) = delete;
9748
    serializer& operator=(const serializer&) = delete;
9749
9750
    /*!
9751
    @brief internal implementation of the serialization function
9752
9753
    This function is called by the public member function dump and organizes
9754
    the serialization internally. The indentation level is propagated as
9755
    additional parameter. In case of arrays and objects, the function is
9756
    called recursively.
9757
9758
    - strings and object keys are escaped using `escape_string()`
9759
    - integer numbers are converted implicitly via `operator<<`
9760
    - floating-point numbers are converted to a string using `"%g"` format
9761
9762
    @param[in] val             value to serialize
9763
    @param[in] pretty_print    whether the output shall be pretty-printed
9764
    @param[in] indent_step     the indent level
9765
    @param[in] current_indent  the current indent level (only used internally)
9766
    */
9767
    void dump(const BasicJsonType& val, const bool pretty_print,
9768
              const bool ensure_ascii,
9769
              const unsigned int indent_step,
9770
              const unsigned int current_indent = 0)
9771
2.59k
    {
9772
2.59k
        switch (val.m_type)
9773
2.59k
        {
9774
2.59k
            case value_t::object:
9775
597
            {
9776
597
                if (val.m_value.object->empty())
9777
0
                {
9778
0
                    o->write_characters("{}", 2);
9779
0
                    return;
9780
0
                }
9781
597
9782
597
                if (pretty_print)
9783
360
                {
9784
360
                    o->write_characters("{\n", 2);
9785
360
9786
360
                    // variable to hold indentation for recursive calls
9787
360
                    const auto new_indent = current_indent + indent_step;
9788
360
                    if (JSON_UNLIKELY(indent_string.size() < new_indent))
9789
360
                    {
9790
0
                        indent_string.resize(indent_string.size() * 2, ' ');
9791
0
                    }
9792
360
9793
360
                    // first n-1 elements
9794
360
                    auto i = val.m_value.object->cbegin();
9795
1.67k
                    for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
9796
1.31k
                    {
9797
1.31k
                        o->write_characters(indent_string.c_str(), new_indent);
9798
1.31k
                        o->write_character('\"');
9799
1.31k
                        dump_escaped(i->first, ensure_ascii);
9800
1.31k
                        o->write_characters("\": ", 3);
9801
1.31k
                        dump(i->second, true, ensure_ascii, indent_step, new_indent);
9802
1.31k
                        o->write_characters(",\n", 2);
9803
1.31k
                    }
9804
360
9805
360
                    // last element
9806
360
                    assert(i != val.m_value.object->cend());
9807
360
                    assert(std::next(i) == val.m_value.object->cend());
9808
360
                    o->write_characters(indent_string.c_str(), new_indent);
9809
360
                    o->write_character('\"');
9810
360
                    dump_escaped(i->first, ensure_ascii);
9811
360
                    o->write_characters("\": ", 3);
9812
360
                    dump(i->second, true, ensure_ascii, indent_step, new_indent);
9813
360
9814
360
                    o->write_character('\n');
9815
360
                    o->write_characters(indent_string.c_str(), current_indent);
9816
360
                    o->write_character('}');
9817
360
                }
9818
237
                else
9819
237
                {
9820
237
                    o->write_character('{');
9821
237
9822
237
                    // first n-1 elements
9823
237
                    auto i = val.m_value.object->cbegin();
9824
801
                    for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
9825
564
                    {
9826
564
                        o->write_character('\"');
9827
564
                        dump_escaped(i->first, ensure_ascii);
9828
564
                        o->write_characters("\":", 2);
9829
564
                        dump(i->second, false, ensure_ascii, indent_step, current_indent);
9830
564
                        o->write_character(',');
9831
564
                    }
9832
237
9833
237
                    // last element
9834
237
                    assert(i != val.m_value.object->cend());
9835
237
                    assert(std::next(i) == val.m_value.object->cend());
9836
237
                    o->write_character('\"');
9837
237
                    dump_escaped(i->first, ensure_ascii);
9838
237
                    o->write_characters("\":", 2);
9839
237
                    dump(i->second, false, ensure_ascii, indent_step, current_indent);
9840
237
9841
237
                    o->write_character('}');
9842
237
                }
9843
597
9844
597
                return;
9845
597
            }
9846
597
9847
597
            case value_t::array:
9848
1
            {
9849
1
                if (val.m_value.array->empty())
9850
0
                {
9851
0
                    o->write_characters("[]", 2);
9852
0
                    return;
9853
0
                }
9854
1
9855
1
                if (pretty_print)
9856
1
                {
9857
1
                    o->write_characters("[\n", 2);
9858
1
9859
1
                    // variable to hold indentation for recursive calls
9860
1
                    const auto new_indent = current_indent + indent_step;
9861
1
                    if (JSON_UNLIKELY(indent_string.size() < new_indent))
9862
1
                    {
9863
0
                        indent_string.resize(indent_string.size() * 2, ' ');
9864
0
                    }
9865
1
9866
1
                    // first n-1 elements
9867
1
                    for (auto i = val.m_value.array->cbegin();
9868
1
                            i != val.m_value.array->cend() - 1; ++i)
9869
0
                    {
9870
0
                        o->write_characters(indent_string.c_str(), new_indent);
9871
0
                        dump(*i, true, ensure_ascii, indent_step, new_indent);
9872
0
                        o->write_characters(",\n", 2);
9873
0
                    }
9874
1
9875
1
                    // last element
9876
1
                    assert(not val.m_value.array->empty());
9877
1
                    o->write_characters(indent_string.c_str(), new_indent);
9878
1
                    dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
9879
1
9880
1
                    o->write_character('\n');
9881
1
                    o->write_characters(indent_string.c_str(), current_indent);
9882
1
                    o->write_character(']');
9883
1
                }
9884
0
                else
9885
0
                {
9886
0
                    o->write_character('[');
9887
0
9888
0
                    // first n-1 elements
9889
0
                    for (auto i = val.m_value.array->cbegin();
9890
0
                            i != val.m_value.array->cend() - 1; ++i)
9891
0
                    {
9892
0
                        dump(*i, false, ensure_ascii, indent_step, current_indent);
9893
0
                        o->write_character(',');
9894
0
                    }
9895
0
9896
0
                    // last element
9897
0
                    assert(not val.m_value.array->empty());
9898
0
                    dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
9899
0
9900
0
                    o->write_character(']');
9901
0
                }
9902
1
9903
1
                return;
9904
1
            }
9905
1
9906
1.67k
            case value_t::string:
9907
1.67k
            {
9908
1.67k
                o->write_character('\"');
9909
1.67k
                dump_escaped(*val.m_value.string, ensure_ascii);
9910
1.67k
                o->write_character('\"');
9911
1.67k
                return;
9912
1
            }
9913
1
9914
2
            case value_t::boolean:
9915
2
            {
9916
2
                if (val.m_value.boolean)
9917
2
                {
9918
2
                    o->write_characters("true", 4);
9919
2
                }
9920
0
                else
9921
0
                {
9922
0
                    o->write_characters("false", 5);
9923
0
                }
9924
2
                return;
9925
1
            }
9926
1
9927
2
            case value_t::number_integer:
9928
2
            {
9929
2
                dump_integer(val.m_value.number_integer);
9930
2
                return;
9931
1
            }
9932
1
9933
293
            case value_t::number_unsigned:
9934
293
            {
9935
293
                dump_integer(val.m_value.number_unsigned);
9936
293
                return;
9937
1
            }
9938
1
9939
7
            case value_t::number_float:
9940
7
            {
9941
7
                dump_float(val.m_value.number_float);
9942
7
                return;
9943
1
            }
9944
1
9945
1
            case value_t::discarded:
9946
0
            {
9947
0
                o->write_characters("<discarded>", 11);
9948
0
                return;
9949
1
            }
9950
1
9951
14
            case value_t::null:
9952
14
            {
9953
14
                o->write_characters("null", 4);
9954
14
                return;
9955
0
            }
9956
0
        }
9957
0
    }
9958
9959
  private:
9960
    /*!
9961
    @brief dump escaped string
9962
9963
    Escape a string by replacing certain special characters by a sequence of an
9964
    escape character (backslash) and another character and other control
9965
    characters by a sequence of "\u" followed by a four-digit hex
9966
    representation. The escaped string is written to output stream @a o.
9967
9968
    @param[in] s  the string to escape
9969
    @param[in] ensure_ascii  whether to escape non-ASCII characters with
9970
                             \uXXXX sequences
9971
9972
    @complexity Linear in the length of string @a s.
9973
    */
9974
    void dump_escaped(const string_t& s, const bool ensure_ascii)
9975
4.14k
    {
9976
4.14k
        uint32_t codepoint;
9977
4.14k
        uint8_t state = UTF8_ACCEPT;
9978
4.14k
        std::size_t bytes = 0;  // number of bytes written to string_buffer
9979
4.14k
9980
27.6k
        for (std::size_t i = 0; i < s.size(); ++i)
9981
23.5k
        {
9982
23.5k
            const auto byte = static_cast<uint8_t>(s[i]);
9983
23.5k
9984
23.5k
            switch (decode(state, codepoint, byte))
9985
23.5k
            {
9986
23.5k
                case UTF8_ACCEPT:  // decode found a new code point
9987
23.5k
                {
9988
23.5k
                    switch (codepoint)
9989
23.5k
                    {
9990
23.5k
                        case 0x08: // backspace
9991
0
                        {
9992
0
                            string_buffer[bytes++] = '\\';
9993
0
                            string_buffer[bytes++] = 'b';
9994
0
                            break;
9995
23.5k
                        }
9996
23.5k
9997
23.5k
                        case 0x09: // horizontal tab
9998
0
                        {
9999
0
                            string_buffer[bytes++] = '\\';
10000
0
                            string_buffer[bytes++] = 't';
10001
0
                            break;
10002
23.5k
                        }
10003
23.5k
10004
23.5k
                        case 0x0A: // newline
10005
0
                        {
10006
0
                            string_buffer[bytes++] = '\\';
10007
0
                            string_buffer[bytes++] = 'n';
10008
0
                            break;
10009
23.5k
                        }
10010
23.5k
10011
23.5k
                        case 0x0C: // formfeed
10012
0
                        {
10013
0
                            string_buffer[bytes++] = '\\';
10014
0
                            string_buffer[bytes++] = 'f';
10015
0
                            break;
10016
23.5k
                        }
10017
23.5k
10018
23.5k
                        case 0x0D: // carriage return
10019
0
                        {
10020
0
                            string_buffer[bytes++] = '\\';
10021
0
                            string_buffer[bytes++] = 'r';
10022
0
                            break;
10023
23.5k
                        }
10024
23.5k
10025
23.5k
                        case 0x22: // quotation mark
10026
0
                        {
10027
0
                            string_buffer[bytes++] = '\\';
10028
0
                            string_buffer[bytes++] = '\"';
10029
0
                            break;
10030
23.5k
                        }
10031
23.5k
10032
23.5k
                        case 0x5C: // reverse solidus
10033
0
                        {
10034
0
                            string_buffer[bytes++] = '\\';
10035
0
                            string_buffer[bytes++] = '\\';
10036
0
                            break;
10037
23.5k
                        }
10038
23.5k
10039
23.5k
                        default:
10040
23.5k
                        {
10041
23.5k
                            // escape control characters (0x00..0x1F) or, if
10042
23.5k
                            // ensure_ascii parameter is used, non-ASCII characters
10043
23.5k
                            if ((codepoint <= 0x1F) or (ensure_ascii and (codepoint >= 0x7F)))
10044
0
                            {
10045
0
                                if (codepoint <= 0xFFFF)
10046
0
                                {
10047
0
                                    std::snprintf(string_buffer.data() + bytes, 7, "\\u%04x",
10048
0
                                                  static_cast<uint16_t>(codepoint));
10049
0
                                    bytes += 6;
10050
0
                                }
10051
0
                                else
10052
0
                                {
10053
0
                                    std::snprintf(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
10054
0
                                                  static_cast<uint16_t>(0xD7C0 + (codepoint >> 10)),
10055
0
                                                  static_cast<uint16_t>(0xDC00 + (codepoint & 0x3FF)));
10056
0
                                    bytes += 12;
10057
0
                                }
10058
0
                            }
10059
23.5k
                            else
10060
23.5k
                            {
10061
23.5k
                                // copy byte to buffer (all previous bytes
10062
23.5k
                                // been copied have in default case above)
10063
23.5k
                                string_buffer[bytes++] = s[i];
10064
23.5k
                            }
10065
23.5k
                            break;
10066
23.5k
                        }
10067
23.5k
                    }
10068
23.5k
10069
23.5k
                    // write buffer and reset index; there must be 13 bytes
10070
23.5k
                    // left, as this is the maximal number of bytes to be
10071
23.5k
                    // written ("\uxxxx\uxxxx\0") for one code point
10072
23.5k
                    if (string_buffer.size() - bytes < 13)
10073
0
                    {
10074
0
                        o->write_characters(string_buffer.data(), bytes);
10075
0
                        bytes = 0;
10076
0
                    }
10077
23.5k
                    break;
10078
23.5k
                }
10079
23.5k
10080
23.5k
                case UTF8_REJECT:  // decode found invalid UTF-8 byte
10081
0
                {
10082
0
                    std::string sn(3, '\0');
10083
0
                    snprintf(&sn[0], sn.size(), "%.2X", byte);
10084
0
                    JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + sn));
10085
23.5k
                }
10086
23.5k
10087
23.5k
                default:  // decode found yet incomplete multi-byte code point
10088
0
                {
10089
0
                    if (not ensure_ascii)
10090
0
                    {
10091
0
                        // code point will not be escaped - copy byte to buffer
10092
0
                        string_buffer[bytes++] = s[i];
10093
0
                    }
10094
0
                    break;
10095
23.5k
                }
10096
23.5k
            }
10097
23.5k
        }
10098
4.14k
10099
4.14k
        if (JSON_LIKELY(state == UTF8_ACCEPT))
10100
4.14k
        {
10101
4.14k
            // write buffer
10102
4.14k
            if (bytes > 0)
10103
4.14k
            {
10104
4.14k
                o->write_characters(string_buffer.data(), bytes);
10105
4.14k
            }
10106
4.14k
        }
10107
0
        else
10108
0
        {
10109
0
            // we finish reading, but do not accept: string was incomplete
10110
0
            std::string sn(3, '\0');
10111
0
            snprintf(&sn[0], sn.size(), "%.2X", static_cast<uint8_t>(s.back()));
10112
0
            JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + sn));
10113
0
        }
10114
4.14k
    }
10115
10116
    /*!
10117
    @brief dump an integer
10118
10119
    Dump a given integer to output stream @a o. Works internally with
10120
    @a number_buffer.
10121
10122
    @param[in] x  integer number (signed or unsigned) to dump
10123
    @tparam NumberType either @a number_integer_t or @a number_unsigned_t
10124
    */
10125
    template<typename NumberType, detail::enable_if_t<
10126
                 std::is_same<NumberType, number_unsigned_t>::value or
10127
                 std::is_same<NumberType, number_integer_t>::value,
10128
                 int> = 0>
10129
    void dump_integer(NumberType x)
10130
295
    {
10131
295
        // special case for "0"
10132
295
        if (x == 0)
10133
11
        {
10134
11
            o->write_character('0');
10135
11
            return;
10136
11
        }
10137
284
10138
284
        const bool is_negative = (x <= 0) and (x != 0);  // see issue #755
10139
284
        std::size_t i = 0;
10140
284
10141
797
        while (x != 0)
10142
513
        {
10143
513
            // spare 1 byte for '\0'
10144
513
            assert(i < number_buffer.size() - 1);
10145
513
10146
513
            const auto digit = std::labs(static_cast<long>(x % 10));
10147
513
            number_buffer[i++] = static_cast<char>('0' + digit);
10148
513
            x /= 10;
10149
513
        }
10150
284
10151
284
        if (is_negative)
10152
1
        {
10153
1
            // make sure there is capacity for the '-'
10154
1
            assert(i < number_buffer.size() - 2);
10155
1
            number_buffer[i++] = '-';
10156
1
        }
10157
284
10158
284
        std::reverse(number_buffer.begin(), number_buffer.begin() + i);
10159
284
        o->write_characters(number_buffer.data(), i);
10160
284
    }
_ZN8nlohmann6detail10serializerINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEE12dump_integerIlLi0EEEvT_
Line
Count
Source
10130
2
    {
10131
2
        // special case for "0"
10132
2
        if (x == 0)
10133
0
        {
10134
0
            o->write_character('0');
10135
0
            return;
10136
0
        }
10137
2
10138
2
        const bool is_negative = (x <= 0) and (x != 0);  // see issue #755
10139
2
        std::size_t i = 0;
10140
2
10141
9
        while (x != 0)
10142
7
        {
10143
7
            // spare 1 byte for '\0'
10144
7
            assert(i < number_buffer.size() - 1);
10145
7
10146
7
            const auto digit = std::labs(static_cast<long>(x % 10));
10147
7
            number_buffer[i++] = static_cast<char>('0' + digit);
10148
7
            x /= 10;
10149
7
        }
10150
2
10151
2
        if (is_negative)
10152
1
        {
10153
1
            // make sure there is capacity for the '-'
10154
1
            assert(i < number_buffer.size() - 2);
10155
1
            number_buffer[i++] = '-';
10156
1
        }
10157
2
10158
2
        std::reverse(number_buffer.begin(), number_buffer.begin() + i);
10159
2
        o->write_characters(number_buffer.data(), i);
10160
2
    }
_ZN8nlohmann6detail10serializerINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEE12dump_integerImLi0EEEvT_
Line
Count
Source
10130
293
    {
10131
293
        // special case for "0"
10132
293
        if (x == 0)
10133
11
        {
10134
11
            o->write_character('0');
10135
11
            return;
10136
11
        }
10137
282
10138
282
        const bool is_negative = (x <= 0) and (x != 0);  // see issue #755
10139
282
        std::size_t i = 0;
10140
282
10141
788
        while (x != 0)
10142
506
        {
10143
506
            // spare 1 byte for '\0'
10144
506
            assert(i < number_buffer.size() - 1);
10145
506
10146
506
            const auto digit = std::labs(static_cast<long>(x % 10));
10147
506
            number_buffer[i++] = static_cast<char>('0' + digit);
10148
506
            x /= 10;
10149
506
        }
10150
282
10151
282
        if (is_negative)
10152
0
        {
10153
0
            // make sure there is capacity for the '-'
10154
0
            assert(i < number_buffer.size() - 2);
10155
0
            number_buffer[i++] = '-';
10156
0
        }
10157
282
10158
282
        std::reverse(number_buffer.begin(), number_buffer.begin() + i);
10159
282
        o->write_characters(number_buffer.data(), i);
10160
282
    }
10161
10162
    /*!
10163
    @brief dump a floating-point number
10164
10165
    Dump a given floating-point number to output stream @a o. Works internally
10166
    with @a number_buffer.
10167
10168
    @param[in] x  floating-point number to dump
10169
    */
10170
    void dump_float(number_float_t x)
10171
7
    {
10172
7
        // NaN / inf
10173
7
        if (not std::isfinite(x))
10174
0
        {
10175
0
            o->write_characters("null", 4);
10176
0
            return;
10177
0
        }
10178
7
10179
7
        // If number_float_t is an IEEE-754 single or double precision number,
10180
7
        // use the Grisu2 algorithm to produce short numbers which are
10181
7
        // guaranteed to round-trip, using strtof and strtod, resp.
10182
7
        //
10183
7
        // NB: The test below works if <long double> == <double>.
10184
7
        static constexpr bool is_ieee_single_or_double
10185
7
            = (std::numeric_limits<number_float_t>::is_iec559 and std::numeric_limits<number_float_t>::digits == 24 and std::numeric_limits<number_float_t>::max_exponent == 128) or
10186
7
              (std::numeric_limits<number_float_t>::is_iec559 and std::numeric_limits<number_float_t>::digits == 53 and std::numeric_limits<number_float_t>::max_exponent == 1024);
10187
7
10188
7
        dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
10189
7
    }
10190
10191
    void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
10192
7
    {
10193
7
        char* begin = number_buffer.data();
10194
7
        char* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
10195
7
10196
7
        o->write_characters(begin, static_cast<size_t>(end - begin));
10197
7
    }
10198
10199
    void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
10200
    {
10201
        // get number of digits for a float -> text -> float round-trip
10202
        static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
10203
10204
        // the actual conversion
10205
        std::ptrdiff_t len = snprintf(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
10206
10207
        // negative value indicates an error
10208
        assert(len > 0);
10209
        // check if buffer was large enough
10210
        assert(static_cast<std::size_t>(len) < number_buffer.size());
10211
10212
        // erase thousands separator
10213
        if (thousands_sep != '\0')
10214
        {
10215
            const auto end = std::remove(number_buffer.begin(),
10216
                                         number_buffer.begin() + len, thousands_sep);
10217
            std::fill(end, number_buffer.end(), '\0');
10218
            assert((end - number_buffer.begin()) <= len);
10219
            len = (end - number_buffer.begin());
10220
        }
10221
10222
        // convert decimal point to '.'
10223
        if (decimal_point != '\0' and decimal_point != '.')
10224
        {
10225
            const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
10226
            if (dec_pos != number_buffer.end())
10227
            {
10228
                *dec_pos = '.';
10229
            }
10230
        }
10231
10232
        o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
10233
10234
        // determine if need to append ".0"
10235
        const bool value_is_int_like =
10236
            std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
10237
                         [](char c)
10238
        {
10239
            return (c == '.' or c == 'e');
10240
        });
10241
10242
        if (value_is_int_like)
10243
        {
10244
            o->write_characters(".0", 2);
10245
        }
10246
    }
10247
10248
    /*!
10249
    @brief check whether a string is UTF-8 encoded
10250
10251
    The function checks each byte of a string whether it is UTF-8 encoded. The
10252
    result of the check is stored in the @a state parameter. The function must
10253
    be called initially with state 0 (accept). State 1 means the string must
10254
    be rejected, because the current byte is not allowed. If the string is
10255
    completely processed, but the state is non-zero, the string ended
10256
    prematurely; that is, the last byte indicated more bytes should have
10257
    followed.
10258
10259
    @param[in,out] state  the state of the decoding
10260
    @param[in,out] codep  codepoint (valid only if resulting state is UTF8_ACCEPT)
10261
    @param[in] byte       next byte to decode
10262
    @return               new state
10263
10264
    @note The function has been edited: a std::array is used.
10265
10266
    @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
10267
    @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
10268
    */
10269
    static uint8_t decode(uint8_t& state, uint32_t& codep, const uint8_t byte) noexcept
10270
23.5k
    {
10271
23.5k
        static const std::array<uint8_t, 400> utf8d =
10272
23.5k
        {
10273
23.5k
            {
10274
23.5k
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F
10275
23.5k
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F
10276
23.5k
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F
10277
23.5k
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F
10278
23.5k
                1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F
10279
23.5k
                7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF
10280
23.5k
                8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF
10281
23.5k
                0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
10282
23.5k
                0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
10283
23.5k
                0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
10284
23.5k
                1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2
10285
23.5k
                1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4
10286
23.5k
                1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6
10287
23.5k
                1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8
10288
23.5k
            }
10289
23.5k
        };
10290
23.5k
10291
23.5k
        const uint8_t type = utf8d[byte];
10292
23.5k
10293
23.5k
        codep = (state != UTF8_ACCEPT)
10294
23.5k
                ? (byte & 0x3fu) | (codep << 6)
10295
23.5k
                : static_cast<uint32_t>(0xff >> type) & (byte);
10296
23.5k
10297
23.5k
        state = utf8d[256u + state * 16u + type];
10298
23.5k
        return state;
10299
23.5k
    }
10300
10301
  private:
10302
    /// the output of the serializer
10303
    output_adapter_t<char> o = nullptr;
10304
10305
    /// a (hopefully) large enough character buffer
10306
    std::array<char, 64> number_buffer{{}};
10307
10308
    /// the locale
10309
    const std::lconv* loc = nullptr;
10310
    /// the locale's thousand separator character
10311
    const char thousands_sep = '\0';
10312
    /// the locale's decimal point character
10313
    const char decimal_point = '\0';
10314
10315
    /// string buffer
10316
    std::array<char, 512> string_buffer{{}};
10317
10318
    /// the indentation character
10319
    const char indent_char;
10320
    /// the indentation string
10321
    string_t indent_string;
10322
};
10323
}
10324
}
10325
10326
// #include <nlohmann/detail/json_ref.hpp>
10327
10328
10329
#include <initializer_list>
10330
#include <utility>
10331
10332
namespace nlohmann
10333
{
10334
namespace detail
10335
{
10336
template<typename BasicJsonType>
10337
class json_ref
10338
{
10339
  public:
10340
    using value_type = BasicJsonType;
10341
10342
    json_ref(value_type&& value)
10343
        : owned_value(std::move(value)), value_ref(&owned_value), is_rvalue(true)
10344
    {}
10345
10346
    json_ref(const value_type& value)
10347
        : value_ref(const_cast<value_type*>(&value)), is_rvalue(false)
10348
    {}
10349
10350
    json_ref(std::initializer_list<json_ref> init)
10351
        : owned_value(init), value_ref(&owned_value), is_rvalue(true)
10352
    {}
10353
10354
    template<class... Args>
10355
    json_ref(Args&& ... args)
10356
        : owned_value(std::forward<Args>(args)...), value_ref(&owned_value), is_rvalue(true)
10357
    {}
10358
10359
    // class should be movable only
10360
    json_ref(json_ref&&) = default;
10361
    json_ref(const json_ref&) = delete;
10362
    json_ref& operator=(const json_ref&) = delete;
10363
10364
    value_type moved_or_copied() const
10365
    {
10366
        if (is_rvalue)
10367
        {
10368
            return std::move(*value_ref);
10369
        }
10370
        return *value_ref;
10371
    }
10372
10373
    value_type const& operator*() const
10374
    {
10375
        return *static_cast<value_type const*>(value_ref);
10376
    }
10377
10378
    value_type const* operator->() const
10379
    {
10380
        return static_cast<value_type const*>(value_ref);
10381
    }
10382
10383
  private:
10384
    mutable value_type owned_value = nullptr;
10385
    value_type* value_ref = nullptr;
10386
    const bool is_rvalue;
10387
};
10388
}
10389
}
10390
10391
// #include <nlohmann/detail/json_pointer.hpp>
10392
10393
10394
#include <cassert> // assert
10395
#include <numeric> // accumulate
10396
#include <string> // string
10397
#include <vector> // vector
10398
10399
// #include <nlohmann/detail/macro_scope.hpp>
10400
10401
// #include <nlohmann/detail/exceptions.hpp>
10402
10403
// #include <nlohmann/detail/value_t.hpp>
10404
10405
10406
namespace nlohmann
10407
{
10408
template<typename BasicJsonType>
10409
class json_pointer
10410
{
10411
    // allow basic_json to access private members
10412
    NLOHMANN_BASIC_JSON_TPL_DECLARATION
10413
    friend class basic_json;
10414
10415
  public:
10416
    /*!
10417
    @brief create JSON pointer
10418
10419
    Create a JSON pointer according to the syntax described in
10420
    [Section 3 of RFC6901](https://tools.ietf.org/html/rfc6901#section-3).
10421
10422
    @param[in] s  string representing the JSON pointer; if omitted, the empty
10423
                  string is assumed which references the whole JSON value
10424
10425
    @throw parse_error.107 if the given JSON pointer @a s is nonempty and does
10426
                           not begin with a slash (`/`); see example below
10427
10428
    @throw parse_error.108 if a tilde (`~`) in the given JSON pointer @a s is
10429
    not followed by `0` (representing `~`) or `1` (representing `/`); see
10430
    example below
10431
10432
    @liveexample{The example shows the construction several valid JSON pointers
10433
    as well as the exceptional behavior.,json_pointer}
10434
10435
    @since version 2.0.0
10436
    */
10437
    explicit json_pointer(const std::string& s = "")
10438
        : reference_tokens(split(s))
10439
    {}
10440
10441
    /*!
10442
    @brief return a string representation of the JSON pointer
10443
10444
    @invariant For each JSON pointer `ptr`, it holds:
10445
    @code {.cpp}
10446
    ptr == json_pointer(ptr.to_string());
10447
    @endcode
10448
10449
    @return a string representation of the JSON pointer
10450
10451
    @liveexample{The example shows the result of `to_string`.,
10452
    json_pointer__to_string}
10453
10454
    @since version 2.0.0
10455
    */
10456
    std::string to_string() const noexcept
10457
    {
10458
        return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
10459
                               std::string{},
10460
                               [](const std::string & a, const std::string & b)
10461
        {
10462
            return a + "/" + escape(b);
10463
        });
10464
    }
10465
10466
    /// @copydoc to_string()
10467
    operator std::string() const
10468
    {
10469
        return to_string();
10470
    }
10471
10472
    /*!
10473
    @param[in] s  reference token to be converted into an array index
10474
10475
    @return integer representation of @a s
10476
10477
    @throw out_of_range.404 if string @a s could not be converted to an integer
10478
    */
10479
    static int array_index(const std::string& s)
10480
    {
10481
        std::size_t processed_chars = 0;
10482
        const int res = std::stoi(s, &processed_chars);
10483
10484
        // check if the string was completely read
10485
        if (JSON_UNLIKELY(processed_chars != s.size()))
10486
        {
10487
            JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'"));
10488
        }
10489
10490
        return res;
10491
    }
10492
10493
  private:
10494
    /*!
10495
    @brief remove and return last reference pointer
10496
    @throw out_of_range.405 if JSON pointer has no parent
10497
    */
10498
    std::string pop_back()
10499
    {
10500
        if (JSON_UNLIKELY(is_root()))
10501
        {
10502
            JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
10503
        }
10504
10505
        auto last = reference_tokens.back();
10506
        reference_tokens.pop_back();
10507
        return last;
10508
    }
10509
10510
    /// return whether pointer points to the root document
10511
    bool is_root() const
10512
    {
10513
        return reference_tokens.empty();
10514
    }
10515
10516
    json_pointer top() const
10517
    {
10518
        if (JSON_UNLIKELY(is_root()))
10519
        {
10520
            JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
10521
        }
10522
10523
        json_pointer result = *this;
10524
        result.reference_tokens = {reference_tokens[0]};
10525
        return result;
10526
    }
10527
10528
    /*!
10529
    @brief create and return a reference to the pointed to value
10530
10531
    @complexity Linear in the number of reference tokens.
10532
10533
    @throw parse_error.109 if array index is not a number
10534
    @throw type_error.313 if value cannot be unflattened
10535
    */
10536
    BasicJsonType& get_and_create(BasicJsonType& j) const
10537
    {
10538
        using size_type = typename BasicJsonType::size_type;
10539
        auto result = &j;
10540
10541
        // in case no reference tokens exist, return a reference to the JSON value
10542
        // j which will be overwritten by a primitive value
10543
        for (const auto& reference_token : reference_tokens)
10544
        {
10545
            switch (result->m_type)
10546
            {
10547
                case detail::value_t::null:
10548
                {
10549
                    if (reference_token == "0")
10550
                    {
10551
                        // start a new array if reference token is 0
10552
                        result = &result->operator[](0);
10553
                    }
10554
                    else
10555
                    {
10556
                        // start a new object otherwise
10557
                        result = &result->operator[](reference_token);
10558
                    }
10559
                    break;
10560
                }
10561
10562
                case detail::value_t::object:
10563
                {
10564
                    // create an entry in the object
10565
                    result = &result->operator[](reference_token);
10566
                    break;
10567
                }
10568
10569
                case detail::value_t::array:
10570
                {
10571
                    // create an entry in the array
10572
                    JSON_TRY
10573
                    {
10574
                        result = &result->operator[](static_cast<size_type>(array_index(reference_token)));
10575
                    }
10576
                    JSON_CATCH(std::invalid_argument&)
10577
                    {
10578
                        JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
10579
                    }
10580
                    break;
10581
                }
10582
10583
                /*
10584
                The following code is only reached if there exists a reference
10585
                token _and_ the current value is primitive. In this case, we have
10586
                an error situation, because primitive values may only occur as
10587
                single value; that is, with an empty list of reference tokens.
10588
                */
10589
                default:
10590
                    JSON_THROW(detail::type_error::create(313, "invalid value to unflatten"));
10591
            }
10592
        }
10593
10594
        return *result;
10595
    }
10596
10597
    /*!
10598
    @brief return a reference to the pointed to value
10599
10600
    @note This version does not throw if a value is not present, but tries to
10601
          create nested values instead. For instance, calling this function
10602
          with pointer `"/this/that"` on a null value is equivalent to calling
10603
          `operator[]("this").operator[]("that")` on that value, effectively
10604
          changing the null value to an object.
10605
10606
    @param[in] ptr  a JSON value
10607
10608
    @return reference to the JSON value pointed to by the JSON pointer
10609
10610
    @complexity Linear in the length of the JSON pointer.
10611
10612
    @throw parse_error.106   if an array index begins with '0'
10613
    @throw parse_error.109   if an array index was not a number
10614
    @throw out_of_range.404  if the JSON pointer can not be resolved
10615
    */
10616
    BasicJsonType& get_unchecked(BasicJsonType* ptr) const
10617
    {
10618
        using size_type = typename BasicJsonType::size_type;
10619
        for (const auto& reference_token : reference_tokens)
10620
        {
10621
            // convert null values to arrays or objects before continuing
10622
            if (ptr->m_type == detail::value_t::null)
10623
            {
10624
                // check if reference token is a number
10625
                const bool nums =
10626
                    std::all_of(reference_token.begin(), reference_token.end(),
10627
                                [](const char x)
10628
                {
10629
                    return (x >= '0' and x <= '9');
10630
                });
10631
10632
                // change value to array for numbers or "-" or to object otherwise
10633
                *ptr = (nums or reference_token == "-")
10634
                       ? detail::value_t::array
10635
                       : detail::value_t::object;
10636
            }
10637
10638
            switch (ptr->m_type)
10639
            {
10640
                case detail::value_t::object:
10641
                {
10642
                    // use unchecked object access
10643
                    ptr = &ptr->operator[](reference_token);
10644
                    break;
10645
                }
10646
10647
                case detail::value_t::array:
10648
                {
10649
                    // error condition (cf. RFC 6901, Sect. 4)
10650
                    if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
10651
                    {
10652
                        JSON_THROW(detail::parse_error::create(106, 0,
10653
                                                               "array index '" + reference_token +
10654
                                                               "' must not begin with '0'"));
10655
                    }
10656
10657
                    if (reference_token == "-")
10658
                    {
10659
                        // explicitly treat "-" as index beyond the end
10660
                        ptr = &ptr->operator[](ptr->m_value.array->size());
10661
                    }
10662
                    else
10663
                    {
10664
                        // convert array index to number; unchecked access
10665
                        JSON_TRY
10666
                        {
10667
                            ptr = &ptr->operator[](
10668
                                static_cast<size_type>(array_index(reference_token)));
10669
                        }
10670
                        JSON_CATCH(std::invalid_argument&)
10671
                        {
10672
                            JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
10673
                        }
10674
                    }
10675
                    break;
10676
                }
10677
10678
                default:
10679
                    JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
10680
            }
10681
        }
10682
10683
        return *ptr;
10684
    }
10685
10686
    /*!
10687
    @throw parse_error.106   if an array index begins with '0'
10688
    @throw parse_error.109   if an array index was not a number
10689
    @throw out_of_range.402  if the array index '-' is used
10690
    @throw out_of_range.404  if the JSON pointer can not be resolved
10691
    */
10692
    BasicJsonType& get_checked(BasicJsonType* ptr) const
10693
    {
10694
        using size_type = typename BasicJsonType::size_type;
10695
        for (const auto& reference_token : reference_tokens)
10696
        {
10697
            switch (ptr->m_type)
10698
            {
10699
                case detail::value_t::object:
10700
                {
10701
                    // note: at performs range check
10702
                    ptr = &ptr->at(reference_token);
10703
                    break;
10704
                }
10705
10706
                case detail::value_t::array:
10707
                {
10708
                    if (JSON_UNLIKELY(reference_token == "-"))
10709
                    {
10710
                        // "-" always fails the range check
10711
                        JSON_THROW(detail::out_of_range::create(402,
10712
                                                                "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
10713
                                                                ") is out of range"));
10714
                    }
10715
10716
                    // error condition (cf. RFC 6901, Sect. 4)
10717
                    if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
10718
                    {
10719
                        JSON_THROW(detail::parse_error::create(106, 0,
10720
                                                               "array index '" + reference_token +
10721
                                                               "' must not begin with '0'"));
10722
                    }
10723
10724
                    // note: at performs range check
10725
                    JSON_TRY
10726
                    {
10727
                        ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
10728
                    }
10729
                    JSON_CATCH(std::invalid_argument&)
10730
                    {
10731
                        JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
10732
                    }
10733
                    break;
10734
                }
10735
10736
                default:
10737
                    JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
10738
            }
10739
        }
10740
10741
        return *ptr;
10742
    }
10743
10744
    /*!
10745
    @brief return a const reference to the pointed to value
10746
10747
    @param[in] ptr  a JSON value
10748
10749
    @return const reference to the JSON value pointed to by the JSON
10750
    pointer
10751
10752
    @throw parse_error.106   if an array index begins with '0'
10753
    @throw parse_error.109   if an array index was not a number
10754
    @throw out_of_range.402  if the array index '-' is used
10755
    @throw out_of_range.404  if the JSON pointer can not be resolved
10756
    */
10757
    const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
10758
    {
10759
        using size_type = typename BasicJsonType::size_type;
10760
        for (const auto& reference_token : reference_tokens)
10761
        {
10762
            switch (ptr->m_type)
10763
            {
10764
                case detail::value_t::object:
10765
                {
10766
                    // use unchecked object access
10767
                    ptr = &ptr->operator[](reference_token);
10768
                    break;
10769
                }
10770
10771
                case detail::value_t::array:
10772
                {
10773
                    if (JSON_UNLIKELY(reference_token == "-"))
10774
                    {
10775
                        // "-" cannot be used for const access
10776
                        JSON_THROW(detail::out_of_range::create(402,
10777
                                                                "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
10778
                                                                ") is out of range"));
10779
                    }
10780
10781
                    // error condition (cf. RFC 6901, Sect. 4)
10782
                    if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
10783
                    {
10784
                        JSON_THROW(detail::parse_error::create(106, 0,
10785
                                                               "array index '" + reference_token +
10786
                                                               "' must not begin with '0'"));
10787
                    }
10788
10789
                    // use unchecked array access
10790
                    JSON_TRY
10791
                    {
10792
                        ptr = &ptr->operator[](
10793
                            static_cast<size_type>(array_index(reference_token)));
10794
                    }
10795
                    JSON_CATCH(std::invalid_argument&)
10796
                    {
10797
                        JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
10798
                    }
10799
                    break;
10800
                }
10801
10802
                default:
10803
                    JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
10804
            }
10805
        }
10806
10807
        return *ptr;
10808
    }
10809
10810
    /*!
10811
    @throw parse_error.106   if an array index begins with '0'
10812
    @throw parse_error.109   if an array index was not a number
10813
    @throw out_of_range.402  if the array index '-' is used
10814
    @throw out_of_range.404  if the JSON pointer can not be resolved
10815
    */
10816
    const BasicJsonType& get_checked(const BasicJsonType* ptr) const
10817
    {
10818
        using size_type = typename BasicJsonType::size_type;
10819
        for (const auto& reference_token : reference_tokens)
10820
        {
10821
            switch (ptr->m_type)
10822
            {
10823
                case detail::value_t::object:
10824
                {
10825
                    // note: at performs range check
10826
                    ptr = &ptr->at(reference_token);
10827
                    break;
10828
                }
10829
10830
                case detail::value_t::array:
10831
                {
10832
                    if (JSON_UNLIKELY(reference_token == "-"))
10833
                    {
10834
                        // "-" always fails the range check
10835
                        JSON_THROW(detail::out_of_range::create(402,
10836
                                                                "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
10837
                                                                ") is out of range"));
10838
                    }
10839
10840
                    // error condition (cf. RFC 6901, Sect. 4)
10841
                    if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
10842
                    {
10843
                        JSON_THROW(detail::parse_error::create(106, 0,
10844
                                                               "array index '" + reference_token +
10845
                                                               "' must not begin with '0'"));
10846
                    }
10847
10848
                    // note: at performs range check
10849
                    JSON_TRY
10850
                    {
10851
                        ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
10852
                    }
10853
                    JSON_CATCH(std::invalid_argument&)
10854
                    {
10855
                        JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
10856
                    }
10857
                    break;
10858
                }
10859
10860
                default:
10861
                    JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
10862
            }
10863
        }
10864
10865
        return *ptr;
10866
    }
10867
10868
    /*!
10869
    @brief split the string input to reference tokens
10870
10871
    @note This function is only called by the json_pointer constructor.
10872
          All exceptions below are documented there.
10873
10874
    @throw parse_error.107  if the pointer is not empty or begins with '/'
10875
    @throw parse_error.108  if character '~' is not followed by '0' or '1'
10876
    */
10877
    static std::vector<std::string> split(const std::string& reference_string)
10878
0
    {
10879
0
        std::vector<std::string> result;
10880
0
10881
0
        // special case: empty reference string -> no reference tokens
10882
0
        if (reference_string.empty())
10883
0
        {
10884
0
            return result;
10885
0
        }
10886
0
10887
0
        // check if nonempty reference string begins with slash
10888
0
        if (JSON_UNLIKELY(reference_string[0] != '/'))
10889
0
        {
10890
0
            JSON_THROW(detail::parse_error::create(107, 1,
10891
0
                                                   "JSON pointer must be empty or begin with '/' - was: '" +
10892
0
                                                   reference_string + "'"));
10893
0
        }
10894
0
10895
0
        // extract the reference tokens:
10896
0
        // - slash: position of the last read slash (or end of string)
10897
0
        // - start: position after the previous slash
10898
0
        for (
10899
0
            // search for the first slash after the first character
10900
0
            std::size_t slash = reference_string.find_first_of('/', 1),
10901
0
            // set the beginning of the first reference token
10902
0
            start = 1;
10903
0
            // we can stop if start == string::npos+1 = 0
10904
0
            start != 0;
10905
0
            // set the beginning of the next reference token
10906
0
            // (will eventually be 0 if slash == std::string::npos)
10907
0
            start = slash + 1,
10908
0
            // find next slash
10909
0
            slash = reference_string.find_first_of('/', start))
10910
0
        {
10911
0
            // use the text between the beginning of the reference token
10912
0
            // (start) and the last slash (slash).
10913
0
            auto reference_token = reference_string.substr(start, slash - start);
10914
0
10915
0
            // check reference tokens are properly escaped
10916
0
            for (std::size_t pos = reference_token.find_first_of('~');
10917
0
                    pos != std::string::npos;
10918
0
                    pos = reference_token.find_first_of('~', pos + 1))
10919
0
            {
10920
0
                assert(reference_token[pos] == '~');
10921
0
10922
0
                // ~ must be followed by 0 or 1
10923
0
                if (JSON_UNLIKELY(pos == reference_token.size() - 1 or
10924
0
                                  (reference_token[pos + 1] != '0' and
10925
0
                                   reference_token[pos + 1] != '1')))
10926
0
                {
10927
0
                    JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'"));
10928
0
                }
10929
0
            }
10930
0
10931
0
            // finally, store the reference token
10932
0
            unescape(reference_token);
10933
0
            result.push_back(reference_token);
10934
0
        }
10935
0
10936
0
        return result;
10937
0
    }
10938
10939
    /*!
10940
    @brief replace all occurrences of a substring by another string
10941
10942
    @param[in,out] s  the string to manipulate; changed so that all
10943
                   occurrences of @a f are replaced with @a t
10944
    @param[in]     f  the substring to replace with @a t
10945
    @param[in]     t  the string to replace @a f
10946
10947
    @pre The search string @a f must not be empty. **This precondition is
10948
    enforced with an assertion.**
10949
10950
    @since version 2.0.0
10951
    */
10952
    static void replace_substring(std::string& s, const std::string& f,
10953
                                  const std::string& t)
10954
0
    {
10955
0
        assert(not f.empty());
10956
0
        for (auto pos = s.find(f);                // find first occurrence of f
10957
0
                pos != std::string::npos;         // make sure f was found
10958
0
                s.replace(pos, f.size(), t),      // replace with t, and
10959
0
                pos = s.find(f, pos + t.size()))  // find next occurrence of f
10960
0
        {}
10961
0
    }
10962
10963
    /// escape "~"" to "~0" and "/" to "~1"
10964
    static std::string escape(std::string s)
10965
    {
10966
        replace_substring(s, "~", "~0");
10967
        replace_substring(s, "/", "~1");
10968
        return s;
10969
    }
10970
10971
    /// unescape "~1" to tilde and "~0" to slash (order is important!)
10972
    static void unescape(std::string& s)
10973
0
    {
10974
0
        replace_substring(s, "~1", "/");
10975
0
        replace_substring(s, "~0", "~");
10976
0
    }
10977
10978
    /*!
10979
    @param[in] reference_string  the reference string to the current value
10980
    @param[in] value             the value to consider
10981
    @param[in,out] result        the result object to insert values to
10982
10983
    @note Empty objects or arrays are flattened to `null`.
10984
    */
10985
    static void flatten(const std::string& reference_string,
10986
                        const BasicJsonType& value,
10987
                        BasicJsonType& result)
10988
    {
10989
        switch (value.m_type)
10990
        {
10991
            case detail::value_t::array:
10992
            {
10993
                if (value.m_value.array->empty())
10994
                {
10995
                    // flatten empty array as null
10996
                    result[reference_string] = nullptr;
10997
                }
10998
                else
10999
                {
11000
                    // iterate array and use index as reference string
11001
                    for (std::size_t i = 0; i < value.m_value.array->size(); ++i)
11002
                    {
11003
                        flatten(reference_string + "/" + std::to_string(i),
11004
                                value.m_value.array->operator[](i), result);
11005
                    }
11006
                }
11007
                break;
11008
            }
11009
11010
            case detail::value_t::object:
11011
            {
11012
                if (value.m_value.object->empty())
11013
                {
11014
                    // flatten empty object as null
11015
                    result[reference_string] = nullptr;
11016
                }
11017
                else
11018
                {
11019
                    // iterate object and use keys as reference string
11020
                    for (const auto& element : *value.m_value.object)
11021
                    {
11022
                        flatten(reference_string + "/" + escape(element.first), element.second, result);
11023
                    }
11024
                }
11025
                break;
11026
            }
11027
11028
            default:
11029
            {
11030
                // add primitive value with its reference string
11031
                result[reference_string] = value;
11032
                break;
11033
            }
11034
        }
11035
    }
11036
11037
    /*!
11038
    @param[in] value  flattened JSON
11039
11040
    @return unflattened JSON
11041
11042
    @throw parse_error.109 if array index is not a number
11043
    @throw type_error.314  if value is not an object
11044
    @throw type_error.315  if object values are not primitive
11045
    @throw type_error.313  if value cannot be unflattened
11046
    */
11047
    static BasicJsonType
11048
    unflatten(const BasicJsonType& value)
11049
    {
11050
        if (JSON_UNLIKELY(not value.is_object()))
11051
        {
11052
            JSON_THROW(detail::type_error::create(314, "only objects can be unflattened"));
11053
        }
11054
11055
        BasicJsonType result;
11056
11057
        // iterate the JSON object values
11058
        for (const auto& element : *value.m_value.object)
11059
        {
11060
            if (JSON_UNLIKELY(not element.second.is_primitive()))
11061
            {
11062
                JSON_THROW(detail::type_error::create(315, "values in object must be primitive"));
11063
            }
11064
11065
            // assign value to reference pointed to by JSON pointer; Note that if
11066
            // the JSON pointer is "" (i.e., points to the whole value), function
11067
            // get_and_create returns a reference to result itself. An assignment
11068
            // will then create a primitive value.
11069
            json_pointer(element.first).get_and_create(result) = element.second;
11070
        }
11071
11072
        return result;
11073
    }
11074
11075
    friend bool operator==(json_pointer const& lhs,
11076
                           json_pointer const& rhs) noexcept
11077
    {
11078
        return (lhs.reference_tokens == rhs.reference_tokens);
11079
    }
11080
11081
    friend bool operator!=(json_pointer const& lhs,
11082
                           json_pointer const& rhs) noexcept
11083
    {
11084
        return not (lhs == rhs);
11085
    }
11086
11087
    /// the reference tokens
11088
    std::vector<std::string> reference_tokens;
11089
};
11090
}
11091
11092
// #include <nlohmann/adl_serializer.hpp>
11093
11094
11095
#include <utility>
11096
11097
// #include <nlohmann/detail/conversions/from_json.hpp>
11098
11099
// #include <nlohmann/detail/conversions/to_json.hpp>
11100
11101
11102
namespace nlohmann
11103
{
11104
template<typename, typename>
11105
struct adl_serializer
11106
{
11107
    /*!
11108
    @brief convert a JSON value to any value type
11109
11110
    This function is usually called by the `get()` function of the
11111
    @ref basic_json class (either explicit or via conversion operators).
11112
11113
    @param[in] j         JSON value to read from
11114
    @param[in,out] val  value to write to
11115
    */
11116
    template<typename BasicJsonType, typename ValueType>
11117
    static auto from_json(BasicJsonType&& j, ValueType& val) noexcept(
11118
        noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val))) -> decltype(
11119
            ::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void()
11120
        )
11121
11.7k
    {
11122
11.7k
        ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
11123
11.7k
    }
_ZN8nlohmann14adl_serializerIbvE9from_jsonIRKNS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaS0_EEbEEDTcmclL_ZNS_12_GLOBAL__N_19from_jsonEEclsr3stdE7forwardIT_Efp_Efp0_Ecvv_EEOSG_RT0_
Line
Count
Source
11121
2
    {
11122
2
        ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
11123
2
    }
_ZN8nlohmann14adl_serializerINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEvE9from_jsonIRKNS_10basic_jsonISt3mapSt6vectorS6_blmdSaS0_EES6_EEDTcmclL_ZNS_12_GLOBAL__N_19from_jsonEEclsr3stdE7forwardIT_Efp_Efp0_Ecvv_EEOSG_RT0_
Line
Count
Source
11121
11.4k
    {
11122
11.4k
        ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
11123
11.4k
    }
_ZN8nlohmann14adl_serializerIivE9from_jsonIRKNS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaS0_EEiEEDTcmclL_ZNS_12_GLOBAL__N_19from_jsonEEclsr3stdE7forwardIT_Efp_Efp0_Ecvv_EEOSG_RT0_
Line
Count
Source
11121
152
    {
11122
152
        ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
11123
152
    }
_ZN8nlohmann14adl_serializerIdvE9from_jsonIRKNS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaS0_EEdEEDTcmclL_ZNS_12_GLOBAL__N_19from_jsonEEclsr3stdE7forwardIT_Efp_Efp0_Ecvv_EEOSG_RT0_
Line
Count
Source
11121
148
    {
11122
148
        ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
11123
148
    }
11124
11125
    /*!
11126
    @brief convert any value type to a JSON value
11127
11128
    This function is usually called by the constructors of the @ref basic_json
11129
    class.
11130
11131
    @param[in,out] j  JSON value to write to
11132
    @param[in] val     value to read from
11133
    */
11134
    template <typename BasicJsonType, typename ValueType>
11135
    static auto to_json(BasicJsonType& j, ValueType&& val) noexcept(
11136
        noexcept(::nlohmann::to_json(j, std::forward<ValueType>(val))))
11137
    -> decltype(::nlohmann::to_json(j, std::forward<ValueType>(val)),
11138
                void())
11139
207k
    {
11140
207k
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
11141
207k
    }
_ZN8nlohmann14adl_serializerINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEvE7to_jsonINS_10basic_jsonISt3mapSt6vectorS6_blmdSaS0_EERS6_EEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
Line
Count
Source
11139
62.5k
    {
11140
62.5k
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
11141
62.5k
    }
_ZN8nlohmann14adl_serializerIdvE7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaS0_EERdEEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
Line
Count
Source
11139
57.4k
    {
11140
57.4k
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
11141
57.4k
    }
_ZN8nlohmann14adl_serializerIbvE7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaS0_EERbEEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
Line
Count
Source
11139
602
    {
11140
602
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
11141
602
    }
_ZN8nlohmann14adl_serializerIlvE7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaS0_EERlEEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
Line
Count
Source
11139
9.18k
    {
11140
9.18k
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
11141
9.18k
    }
_ZN8nlohmann14adl_serializerImvE7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaS0_EERmEEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
Line
Count
Source
11139
77.0k
    {
11140
77.0k
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
11141
77.0k
    }
_ZN8nlohmann14adl_serializerIA474_cvE7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaS0_EERA474_KcEEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSI_
Line
Count
Source
11139
199
    {
11140
199
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
11141
199
    }
_ZN8nlohmann14adl_serializerINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEvE7to_jsonINS_10basic_jsonISt3mapSt6vectorS6_blmdSaS0_EES6_EEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSE_
Line
Count
Source
11139
423
    {
11140
423
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
11141
423
    }
_ZN8nlohmann14adl_serializerINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEvE7to_jsonINS_10basic_jsonISt3mapSt6vectorS6_blmdSaS0_EEKS6_EEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
Line
Count
Source
11139
47
    {
11140
47
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
11141
47
    }
_ZN8nlohmann14adl_serializerIjvE7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaS0_EERjEEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
Line
Count
Source
11139
141
    {
11140
141
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
11141
141
    }
_ZN8nlohmann14adl_serializerIPKcvE7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaS0_EERKS2_EEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSI_
Line
Count
Source
11139
10
    {
11140
10
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
11141
10
    }
_ZN8nlohmann14adl_serializerIbvE7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaS0_EEbEEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSE_
Line
Count
Source
11139
1
    {
11140
1
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
11141
1
    }
_ZN8nlohmann14adl_serializerIdvE7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaS0_EEdEEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSE_
Line
Count
Source
11139
1
    {
11140
1
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
11141
1
    }
_ZN8nlohmann14adl_serializerIA6_cvE7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaS0_EERA6_KcEEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSI_
Line
Count
Source
11139
1
    {
11140
1
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
11141
1
    }
_ZN8nlohmann14adl_serializerIivE7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaS0_EEiEEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSE_
Line
Count
Source
11139
1
    {
11140
1
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
11141
1
    }
11142
};
11143
}
11144
11145
11146
/*!
11147
@brief namespace for Niels Lohmann
11148
@see https://github.com/nlohmann
11149
@since version 1.0.0
11150
*/
11151
namespace nlohmann
11152
{
11153
11154
/*!
11155
@brief a class to store JSON values
11156
11157
@tparam ObjectType type for JSON objects (`std::map` by default; will be used
11158
in @ref object_t)
11159
@tparam ArrayType type for JSON arrays (`std::vector` by default; will be used
11160
in @ref array_t)
11161
@tparam StringType type for JSON strings and object keys (`std::string` by
11162
default; will be used in @ref string_t)
11163
@tparam BooleanType type for JSON booleans (`bool` by default; will be used
11164
in @ref boolean_t)
11165
@tparam NumberIntegerType type for JSON integer numbers (`int64_t` by
11166
default; will be used in @ref number_integer_t)
11167
@tparam NumberUnsignedType type for JSON unsigned integer numbers (@c
11168
`uint64_t` by default; will be used in @ref number_unsigned_t)
11169
@tparam NumberFloatType type for JSON floating-point numbers (`double` by
11170
default; will be used in @ref number_float_t)
11171
@tparam AllocatorType type of the allocator to use (`std::allocator` by
11172
default)
11173
@tparam JSONSerializer the serializer to resolve internal calls to `to_json()`
11174
and `from_json()` (@ref adl_serializer by default)
11175
11176
@requirement The class satisfies the following concept requirements:
11177
- Basic
11178
 - [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible):
11179
   JSON values can be default constructed. The result will be a JSON null
11180
   value.
11181
 - [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible):
11182
   A JSON value can be constructed from an rvalue argument.
11183
 - [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible):
11184
   A JSON value can be copy-constructed from an lvalue expression.
11185
 - [MoveAssignable](https://en.cppreference.com/w/cpp/named_req/MoveAssignable):
11186
   A JSON value van be assigned from an rvalue argument.
11187
 - [CopyAssignable](https://en.cppreference.com/w/cpp/named_req/CopyAssignable):
11188
   A JSON value can be copy-assigned from an lvalue expression.
11189
 - [Destructible](https://en.cppreference.com/w/cpp/named_req/Destructible):
11190
   JSON values can be destructed.
11191
- Layout
11192
 - [StandardLayoutType](https://en.cppreference.com/w/cpp/named_req/StandardLayoutType):
11193
   JSON values have
11194
   [standard layout](https://en.cppreference.com/w/cpp/language/data_members#Standard_layout):
11195
   All non-static data members are private and standard layout types, the
11196
   class has no virtual functions or (virtual) base classes.
11197
- Library-wide
11198
 - [EqualityComparable](https://en.cppreference.com/w/cpp/named_req/EqualityComparable):
11199
   JSON values can be compared with `==`, see @ref
11200
   operator==(const_reference,const_reference).
11201
 - [LessThanComparable](https://en.cppreference.com/w/cpp/named_req/LessThanComparable):
11202
   JSON values can be compared with `<`, see @ref
11203
   operator<(const_reference,const_reference).
11204
 - [Swappable](https://en.cppreference.com/w/cpp/named_req/Swappable):
11205
   Any JSON lvalue or rvalue of can be swapped with any lvalue or rvalue of
11206
   other compatible types, using unqualified function call @ref swap().
11207
 - [NullablePointer](https://en.cppreference.com/w/cpp/named_req/NullablePointer):
11208
   JSON values can be compared against `std::nullptr_t` objects which are used
11209
   to model the `null` value.
11210
- Container
11211
 - [Container](https://en.cppreference.com/w/cpp/named_req/Container):
11212
   JSON values can be used like STL containers and provide iterator access.
11213
 - [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer);
11214
   JSON values can be used like STL containers and provide reverse iterator
11215
   access.
11216
11217
@invariant The member variables @a m_value and @a m_type have the following
11218
relationship:
11219
- If `m_type == value_t::object`, then `m_value.object != nullptr`.
11220
- If `m_type == value_t::array`, then `m_value.array != nullptr`.
11221
- If `m_type == value_t::string`, then `m_value.string != nullptr`.
11222
The invariants are checked by member function assert_invariant().
11223
11224
@internal
11225
@note ObjectType trick from http://stackoverflow.com/a/9860911
11226
@endinternal
11227
11228
@see [RFC 7159: The JavaScript Object Notation (JSON) Data Interchange
11229
Format](http://rfc7159.net/rfc7159)
11230
11231
@since version 1.0.0
11232
11233
@nosubgrouping
11234
*/
11235
NLOHMANN_BASIC_JSON_TPL_DECLARATION
11236
class basic_json
11237
{
11238
  private:
11239
    template<detail::value_t> friend struct detail::external_constructor;
11240
    friend ::nlohmann::json_pointer<basic_json>;
11241
    friend ::nlohmann::detail::parser<basic_json>;
11242
    friend ::nlohmann::detail::serializer<basic_json>;
11243
    template<typename BasicJsonType>
11244
    friend class ::nlohmann::detail::iter_impl;
11245
    template<typename BasicJsonType, typename CharType>
11246
    friend class ::nlohmann::detail::binary_writer;
11247
    template<typename BasicJsonType, typename SAX>
11248
    friend class ::nlohmann::detail::binary_reader;
11249
    template<typename BasicJsonType>
11250
    friend class ::nlohmann::detail::json_sax_dom_parser;
11251
    template<typename BasicJsonType>
11252
    friend class ::nlohmann::detail::json_sax_dom_callback_parser;
11253
11254
    /// workaround type for MSVC
11255
    using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
11256
11257
    // convenience aliases for types residing in namespace detail;
11258
    using lexer = ::nlohmann::detail::lexer<basic_json>;
11259
    using parser = ::nlohmann::detail::parser<basic_json>;
11260
11261
    using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
11262
    template<typename BasicJsonType>
11263
    using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
11264
    template<typename BasicJsonType>
11265
    using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
11266
    template<typename Iterator>
11267
    using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
11268
    template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
11269
11270
    template<typename CharType>
11271
    using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
11272
11273
    using binary_reader = ::nlohmann::detail::binary_reader<basic_json>;
11274
    template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
11275
11276
    using serializer = ::nlohmann::detail::serializer<basic_json>;
11277
11278
  public:
11279
    using value_t = detail::value_t;
11280
    /// JSON Pointer, see @ref nlohmann::json_pointer
11281
    using json_pointer = ::nlohmann::json_pointer<basic_json>;
11282
    template<typename T, typename SFINAE>
11283
    using json_serializer = JSONSerializer<T, SFINAE>;
11284
    /// helper type for initializer lists of basic_json values
11285
    using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
11286
11287
    using input_format_t = detail::input_format_t;
11288
    /// SAX interface type, see @ref nlohmann::json_sax
11289
    using json_sax_t = json_sax<basic_json>;
11290
11291
    ////////////////
11292
    // exceptions //
11293
    ////////////////
11294
11295
    /// @name exceptions
11296
    /// Classes to implement user-defined exceptions.
11297
    /// @{
11298
11299
    /// @copydoc detail::exception
11300
    using exception = detail::exception;
11301
    /// @copydoc detail::parse_error
11302
    using parse_error = detail::parse_error;
11303
    /// @copydoc detail::invalid_iterator
11304
    using invalid_iterator = detail::invalid_iterator;
11305
    /// @copydoc detail::type_error
11306
    using type_error = detail::type_error;
11307
    /// @copydoc detail::out_of_range
11308
    using out_of_range = detail::out_of_range;
11309
    /// @copydoc detail::other_error
11310
    using other_error = detail::other_error;
11311
11312
    /// @}
11313
11314
11315
    /////////////////////
11316
    // container types //
11317
    /////////////////////
11318
11319
    /// @name container types
11320
    /// The canonic container types to use @ref basic_json like any other STL
11321
    /// container.
11322
    /// @{
11323
11324
    /// the type of elements in a basic_json container
11325
    using value_type = basic_json;
11326
11327
    /// the type of an element reference
11328
    using reference = value_type&;
11329
    /// the type of an element const reference
11330
    using const_reference = const value_type&;
11331
11332
    /// a type to represent differences between iterators
11333
    using difference_type = std::ptrdiff_t;
11334
    /// a type to represent container sizes
11335
    using size_type = std::size_t;
11336
11337
    /// the allocator type
11338
    using allocator_type = AllocatorType<basic_json>;
11339
11340
    /// the type of an element pointer
11341
    using pointer = typename std::allocator_traits<allocator_type>::pointer;
11342
    /// the type of an element const pointer
11343
    using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
11344
11345
    /// an iterator for a basic_json container
11346
    using iterator = iter_impl<basic_json>;
11347
    /// a const iterator for a basic_json container
11348
    using const_iterator = iter_impl<const basic_json>;
11349
    /// a reverse iterator for a basic_json container
11350
    using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
11351
    /// a const reverse iterator for a basic_json container
11352
    using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
11353
11354
    /// @}
11355
11356
11357
    /*!
11358
    @brief returns the allocator associated with the container
11359
    */
11360
    static allocator_type get_allocator()
11361
    {
11362
        return allocator_type();
11363
    }
11364
11365
    /*!
11366
    @brief returns version information on the library
11367
11368
    This function returns a JSON object with information about the library,
11369
    including the version number and information on the platform and compiler.
11370
11371
    @return JSON object holding version information
11372
    key         | description
11373
    ----------- | ---------------
11374
    `compiler`  | Information on the used compiler. It is an object with the following keys: `c++` (the used C++ standard), `family` (the compiler family; possible values are `clang`, `icc`, `gcc`, `ilecpp`, `msvc`, `pgcpp`, `sunpro`, and `unknown`), and `version` (the compiler version).
11375
    `copyright` | The copyright line for the library as string.
11376
    `name`      | The name of the library as string.
11377
    `platform`  | The used platform as string. Possible values are `win32`, `linux`, `apple`, `unix`, and `unknown`.
11378
    `url`       | The URL of the project as string.
11379
    `version`   | The version of the library. It is an object with the following keys: `major`, `minor`, and `patch` as defined by [Semantic Versioning](http://semver.org), and `string` (the version string).
11380
11381
    @liveexample{The following code shows an example output of the `meta()`
11382
    function.,meta}
11383
11384
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
11385
    changes to any JSON value.
11386
11387
    @complexity Constant.
11388
11389
    @since 2.1.0
11390
    */
11391
    static basic_json meta()
11392
    {
11393
        basic_json result;
11394
11395
        result["copyright"] = "(C) 2013-2017 Niels Lohmann";
11396
        result["name"] = "JSON for Modern C++";
11397
        result["url"] = "https://github.com/nlohmann/json";
11398
        result["version"]["string"] =
11399
            std::to_string(NLOHMANN_JSON_VERSION_MAJOR) + "." +
11400
            std::to_string(NLOHMANN_JSON_VERSION_MINOR) + "." +
11401
            std::to_string(NLOHMANN_JSON_VERSION_PATCH);
11402
        result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
11403
        result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
11404
        result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
11405
11406
#ifdef _WIN32
11407
        result["platform"] = "win32";
11408
#elif defined __linux__
11409
        result["platform"] = "linux";
11410
#elif defined __APPLE__
11411
        result["platform"] = "apple";
11412
#elif defined __unix__
11413
        result["platform"] = "unix";
11414
#else
11415
        result["platform"] = "unknown";
11416
#endif
11417
11418
#if defined(__ICC) || defined(__INTEL_COMPILER)
11419
        result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
11420
#elif defined(__clang__)
11421
        result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
11422
#elif defined(__GNUC__) || defined(__GNUG__)
11423
        result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}};
11424
#elif defined(__HP_cc) || defined(__HP_aCC)
11425
        result["compiler"] = "hp"
11426
#elif defined(__IBMCPP__)
11427
        result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
11428
#elif defined(_MSC_VER)
11429
        result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
11430
#elif defined(__PGI)
11431
        result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
11432
#elif defined(__SUNPRO_CC)
11433
        result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
11434
#else
11435
        result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
11436
#endif
11437
11438
#ifdef __cplusplus
11439
        result["compiler"]["c++"] = std::to_string(__cplusplus);
11440
#else
11441
        result["compiler"]["c++"] = "unknown";
11442
#endif
11443
        return result;
11444
    }
11445
11446
11447
    ///////////////////////////
11448
    // JSON value data types //
11449
    ///////////////////////////
11450
11451
    /// @name JSON value data types
11452
    /// The data types to store a JSON value. These types are derived from
11453
    /// the template arguments passed to class @ref basic_json.
11454
    /// @{
11455
11456
#if defined(JSON_HAS_CPP_14)
11457
    // Use transparent comparator if possible, combined with perfect forwarding
11458
    // on find() and count() calls prevents unnecessary string construction.
11459
    using object_comparator_t = std::less<>;
11460
#else
11461
    using object_comparator_t = std::less<StringType>;
11462
#endif
11463
11464
    /*!
11465
    @brief a type for an object
11466
11467
    [RFC 7159](http://rfc7159.net/rfc7159) describes JSON objects as follows:
11468
    > An object is an unordered collection of zero or more name/value pairs,
11469
    > where a name is a string and a value is a string, number, boolean, null,
11470
    > object, or array.
11471
11472
    To store objects in C++, a type is defined by the template parameters
11473
    described below.
11474
11475
    @tparam ObjectType  the container to store objects (e.g., `std::map` or
11476
    `std::unordered_map`)
11477
    @tparam StringType the type of the keys or names (e.g., `std::string`).
11478
    The comparison function `std::less<StringType>` is used to order elements
11479
    inside the container.
11480
    @tparam AllocatorType the allocator to use for objects (e.g.,
11481
    `std::allocator`)
11482
11483
    #### Default type
11484
11485
    With the default values for @a ObjectType (`std::map`), @a StringType
11486
    (`std::string`), and @a AllocatorType (`std::allocator`), the default
11487
    value for @a object_t is:
11488
11489
    @code {.cpp}
11490
    std::map<
11491
      std::string, // key_type
11492
      basic_json, // value_type
11493
      std::less<std::string>, // key_compare
11494
      std::allocator<std::pair<const std::string, basic_json>> // allocator_type
11495
    >
11496
    @endcode
11497
11498
    #### Behavior
11499
11500
    The choice of @a object_t influences the behavior of the JSON class. With
11501
    the default type, objects have the following behavior:
11502
11503
    - When all names are unique, objects will be interoperable in the sense
11504
      that all software implementations receiving that object will agree on
11505
      the name-value mappings.
11506
    - When the names within an object are not unique, it is unspecified which
11507
      one of the values for a given key will be chosen. For instance,
11508
      `{"key": 2, "key": 1}` could be equal to either `{"key": 1}` or
11509
      `{"key": 2}`.
11510
    - Internally, name/value pairs are stored in lexicographical order of the
11511
      names. Objects will also be serialized (see @ref dump) in this order.
11512
      For instance, `{"b": 1, "a": 2}` and `{"a": 2, "b": 1}` will be stored
11513
      and serialized as `{"a": 2, "b": 1}`.
11514
    - When comparing objects, the order of the name/value pairs is irrelevant.
11515
      This makes objects interoperable in the sense that they will not be
11516
      affected by these differences. For instance, `{"b": 1, "a": 2}` and
11517
      `{"a": 2, "b": 1}` will be treated as equal.
11518
11519
    #### Limits
11520
11521
    [RFC 7159](http://rfc7159.net/rfc7159) specifies:
11522
    > An implementation may set limits on the maximum depth of nesting.
11523
11524
    In this class, the object's limit of nesting is not explicitly constrained.
11525
    However, a maximum depth of nesting may be introduced by the compiler or
11526
    runtime environment. A theoretical limit can be queried by calling the
11527
    @ref max_size function of a JSON object.
11528
11529
    #### Storage
11530
11531
    Objects are stored as pointers in a @ref basic_json type. That is, for any
11532
    access to object values, a pointer of type `object_t*` must be
11533
    dereferenced.
11534
11535
    @sa @ref array_t -- type for an array value
11536
11537
    @since version 1.0.0
11538
11539
    @note The order name/value pairs are added to the object is *not*
11540
    preserved by the library. Therefore, iterating an object may return
11541
    name/value pairs in a different order than they were originally stored. In
11542
    fact, keys will be traversed in alphabetical order as `std::map` with
11543
    `std::less` is used by default. Please note this behavior conforms to [RFC
11544
    7159](http://rfc7159.net/rfc7159), because any order implements the
11545
    specified "unordered" nature of JSON objects.
11546
    */
11547
    using object_t = ObjectType<StringType,
11548
          basic_json,
11549
          object_comparator_t,
11550
          AllocatorType<std::pair<const StringType,
11551
          basic_json>>>;
11552
11553
    /*!
11554
    @brief a type for an array
11555
11556
    [RFC 7159](http://rfc7159.net/rfc7159) describes JSON arrays as follows:
11557
    > An array is an ordered sequence of zero or more values.
11558
11559
    To store objects in C++, a type is defined by the template parameters
11560
    explained below.
11561
11562
    @tparam ArrayType  container type to store arrays (e.g., `std::vector` or
11563
    `std::list`)
11564
    @tparam AllocatorType allocator to use for arrays (e.g., `std::allocator`)
11565
11566
    #### Default type
11567
11568
    With the default values for @a ArrayType (`std::vector`) and @a
11569
    AllocatorType (`std::allocator`), the default value for @a array_t is:
11570
11571
    @code {.cpp}
11572
    std::vector<
11573
      basic_json, // value_type
11574
      std::allocator<basic_json> // allocator_type
11575
    >
11576
    @endcode
11577
11578
    #### Limits
11579
11580
    [RFC 7159](http://rfc7159.net/rfc7159) specifies:
11581
    > An implementation may set limits on the maximum depth of nesting.
11582
11583
    In this class, the array's limit of nesting is not explicitly constrained.
11584
    However, a maximum depth of nesting may be introduced by the compiler or
11585
    runtime environment. A theoretical limit can be queried by calling the
11586
    @ref max_size function of a JSON array.
11587
11588
    #### Storage
11589
11590
    Arrays are stored as pointers in a @ref basic_json type. That is, for any
11591
    access to array values, a pointer of type `array_t*` must be dereferenced.
11592
11593
    @sa @ref object_t -- type for an object value
11594
11595
    @since version 1.0.0
11596
    */
11597
    using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
11598
11599
    /*!
11600
    @brief a type for a string
11601
11602
    [RFC 7159](http://rfc7159.net/rfc7159) describes JSON strings as follows:
11603
    > A string is a sequence of zero or more Unicode characters.
11604
11605
    To store objects in C++, a type is defined by the template parameter
11606
    described below. Unicode values are split by the JSON class into
11607
    byte-sized characters during deserialization.
11608
11609
    @tparam StringType  the container to store strings (e.g., `std::string`).
11610
    Note this container is used for keys/names in objects, see @ref object_t.
11611
11612
    #### Default type
11613
11614
    With the default values for @a StringType (`std::string`), the default
11615
    value for @a string_t is:
11616
11617
    @code {.cpp}
11618
    std::string
11619
    @endcode
11620
11621
    #### Encoding
11622
11623
    Strings are stored in UTF-8 encoding. Therefore, functions like
11624
    `std::string::size()` or `std::string::length()` return the number of
11625
    bytes in the string rather than the number of characters or glyphs.
11626
11627
    #### String comparison
11628
11629
    [RFC 7159](http://rfc7159.net/rfc7159) states:
11630
    > Software implementations are typically required to test names of object
11631
    > members for equality. Implementations that transform the textual
11632
    > representation into sequences of Unicode code units and then perform the
11633
    > comparison numerically, code unit by code unit, are interoperable in the
11634
    > sense that implementations will agree in all cases on equality or
11635
    > inequality of two strings. For example, implementations that compare
11636
    > strings with escaped characters unconverted may incorrectly find that
11637
    > `"a\\b"` and `"a\u005Cb"` are not equal.
11638
11639
    This implementation is interoperable as it does compare strings code unit
11640
    by code unit.
11641
11642
    #### Storage
11643
11644
    String values are stored as pointers in a @ref basic_json type. That is,
11645
    for any access to string values, a pointer of type `string_t*` must be
11646
    dereferenced.
11647
11648
    @since version 1.0.0
11649
    */
11650
    using string_t = StringType;
11651
11652
    /*!
11653
    @brief a type for a boolean
11654
11655
    [RFC 7159](http://rfc7159.net/rfc7159) implicitly describes a boolean as a
11656
    type which differentiates the two literals `true` and `false`.
11657
11658
    To store objects in C++, a type is defined by the template parameter @a
11659
    BooleanType which chooses the type to use.
11660
11661
    #### Default type
11662
11663
    With the default values for @a BooleanType (`bool`), the default value for
11664
    @a boolean_t is:
11665
11666
    @code {.cpp}
11667
    bool
11668
    @endcode
11669
11670
    #### Storage
11671
11672
    Boolean values are stored directly inside a @ref basic_json type.
11673
11674
    @since version 1.0.0
11675
    */
11676
    using boolean_t = BooleanType;
11677
11678
    /*!
11679
    @brief a type for a number (integer)
11680
11681
    [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:
11682
    > The representation of numbers is similar to that used in most
11683
    > programming languages. A number is represented in base 10 using decimal
11684
    > digits. It contains an integer component that may be prefixed with an
11685
    > optional minus sign, which may be followed by a fraction part and/or an
11686
    > exponent part. Leading zeros are not allowed. (...) Numeric values that
11687
    > cannot be represented in the grammar below (such as Infinity and NaN)
11688
    > are not permitted.
11689
11690
    This description includes both integer and floating-point numbers.
11691
    However, C++ allows more precise storage if it is known whether the number
11692
    is a signed integer, an unsigned integer or a floating-point number.
11693
    Therefore, three different types, @ref number_integer_t, @ref
11694
    number_unsigned_t and @ref number_float_t are used.
11695
11696
    To store integer numbers in C++, a type is defined by the template
11697
    parameter @a NumberIntegerType which chooses the type to use.
11698
11699
    #### Default type
11700
11701
    With the default values for @a NumberIntegerType (`int64_t`), the default
11702
    value for @a number_integer_t is:
11703
11704
    @code {.cpp}
11705
    int64_t
11706
    @endcode
11707
11708
    #### Default behavior
11709
11710
    - The restrictions about leading zeros is not enforced in C++. Instead,
11711
      leading zeros in integer literals lead to an interpretation as octal
11712
      number. Internally, the value will be stored as decimal number. For
11713
      instance, the C++ integer literal `010` will be serialized to `8`.
11714
      During deserialization, leading zeros yield an error.
11715
    - Not-a-number (NaN) values will be serialized to `null`.
11716
11717
    #### Limits
11718
11719
    [RFC 7159](http://rfc7159.net/rfc7159) specifies:
11720
    > An implementation may set limits on the range and precision of numbers.
11721
11722
    When the default type is used, the maximal integer number that can be
11723
    stored is `9223372036854775807` (INT64_MAX) and the minimal integer number
11724
    that can be stored is `-9223372036854775808` (INT64_MIN). Integer numbers
11725
    that are out of range will yield over/underflow when used in a
11726
    constructor. During deserialization, too large or small integer numbers
11727
    will be automatically be stored as @ref number_unsigned_t or @ref
11728
    number_float_t.
11729
11730
    [RFC 7159](http://rfc7159.net/rfc7159) further states:
11731
    > Note that when such software is used, numbers that are integers and are
11732
    > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense
11733
    > that implementations will agree exactly on their numeric values.
11734
11735
    As this range is a subrange of the exactly supported range [INT64_MIN,
11736
    INT64_MAX], this class's integer type is interoperable.
11737
11738
    #### Storage
11739
11740
    Integer number values are stored directly inside a @ref basic_json type.
11741
11742
    @sa @ref number_float_t -- type for number values (floating-point)
11743
11744
    @sa @ref number_unsigned_t -- type for number values (unsigned integer)
11745
11746
    @since version 1.0.0
11747
    */
11748
    using number_integer_t = NumberIntegerType;
11749
11750
    /*!
11751
    @brief a type for a number (unsigned)
11752
11753
    [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:
11754
    > The representation of numbers is similar to that used in most
11755
    > programming languages. A number is represented in base 10 using decimal
11756
    > digits. It contains an integer component that may be prefixed with an
11757
    > optional minus sign, which may be followed by a fraction part and/or an
11758
    > exponent part. Leading zeros are not allowed. (...) Numeric values that
11759
    > cannot be represented in the grammar below (such as Infinity and NaN)
11760
    > are not permitted.
11761
11762
    This description includes both integer and floating-point numbers.
11763
    However, C++ allows more precise storage if it is known whether the number
11764
    is a signed integer, an unsigned integer or a floating-point number.
11765
    Therefore, three different types, @ref number_integer_t, @ref
11766
    number_unsigned_t and @ref number_float_t are used.
11767
11768
    To store unsigned integer numbers in C++, a type is defined by the
11769
    template parameter @a NumberUnsignedType which chooses the type to use.
11770
11771
    #### Default type
11772
11773
    With the default values for @a NumberUnsignedType (`uint64_t`), the
11774
    default value for @a number_unsigned_t is:
11775
11776
    @code {.cpp}
11777
    uint64_t
11778
    @endcode
11779
11780
    #### Default behavior
11781
11782
    - The restrictions about leading zeros is not enforced in C++. Instead,
11783
      leading zeros in integer literals lead to an interpretation as octal
11784
      number. Internally, the value will be stored as decimal number. For
11785
      instance, the C++ integer literal `010` will be serialized to `8`.
11786
      During deserialization, leading zeros yield an error.
11787
    - Not-a-number (NaN) values will be serialized to `null`.
11788
11789
    #### Limits
11790
11791
    [RFC 7159](http://rfc7159.net/rfc7159) specifies:
11792
    > An implementation may set limits on the range and precision of numbers.
11793
11794
    When the default type is used, the maximal integer number that can be
11795
    stored is `18446744073709551615` (UINT64_MAX) and the minimal integer
11796
    number that can be stored is `0`. Integer numbers that are out of range
11797
    will yield over/underflow when used in a constructor. During
11798
    deserialization, too large or small integer numbers will be automatically
11799
    be stored as @ref number_integer_t or @ref number_float_t.
11800
11801
    [RFC 7159](http://rfc7159.net/rfc7159) further states:
11802
    > Note that when such software is used, numbers that are integers and are
11803
    > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense
11804
    > that implementations will agree exactly on their numeric values.
11805
11806
    As this range is a subrange (when considered in conjunction with the
11807
    number_integer_t type) of the exactly supported range [0, UINT64_MAX],
11808
    this class's integer type is interoperable.
11809
11810
    #### Storage
11811
11812
    Integer number values are stored directly inside a @ref basic_json type.
11813
11814
    @sa @ref number_float_t -- type for number values (floating-point)
11815
    @sa @ref number_integer_t -- type for number values (integer)
11816
11817
    @since version 2.0.0
11818
    */
11819
    using number_unsigned_t = NumberUnsignedType;
11820
11821
    /*!
11822
    @brief a type for a number (floating-point)
11823
11824
    [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:
11825
    > The representation of numbers is similar to that used in most
11826
    > programming languages. A number is represented in base 10 using decimal
11827
    > digits. It contains an integer component that may be prefixed with an
11828
    > optional minus sign, which may be followed by a fraction part and/or an
11829
    > exponent part. Leading zeros are not allowed. (...) Numeric values that
11830
    > cannot be represented in the grammar below (such as Infinity and NaN)
11831
    > are not permitted.
11832
11833
    This description includes both integer and floating-point numbers.
11834
    However, C++ allows more precise storage if it is known whether the number
11835
    is a signed integer, an unsigned integer or a floating-point number.
11836
    Therefore, three different types, @ref number_integer_t, @ref
11837
    number_unsigned_t and @ref number_float_t are used.
11838
11839
    To store floating-point numbers in C++, a type is defined by the template
11840
    parameter @a NumberFloatType which chooses the type to use.
11841
11842
    #### Default type
11843
11844
    With the default values for @a NumberFloatType (`double`), the default
11845
    value for @a number_float_t is:
11846
11847
    @code {.cpp}
11848
    double
11849
    @endcode
11850
11851
    #### Default behavior
11852
11853
    - The restrictions about leading zeros is not enforced in C++. Instead,
11854
      leading zeros in floating-point literals will be ignored. Internally,
11855
      the value will be stored as decimal number. For instance, the C++
11856
      floating-point literal `01.2` will be serialized to `1.2`. During
11857
      deserialization, leading zeros yield an error.
11858
    - Not-a-number (NaN) values will be serialized to `null`.
11859
11860
    #### Limits
11861
11862
    [RFC 7159](http://rfc7159.net/rfc7159) states:
11863
    > This specification allows implementations to set limits on the range and
11864
    > precision of numbers accepted. Since software that implements IEEE
11865
    > 754-2008 binary64 (double precision) numbers is generally available and
11866
    > widely used, good interoperability can be achieved by implementations
11867
    > that expect no more precision or range than these provide, in the sense
11868
    > that implementations will approximate JSON numbers within the expected
11869
    > precision.
11870
11871
    This implementation does exactly follow this approach, as it uses double
11872
    precision floating-point numbers. Note values smaller than
11873
    `-1.79769313486232e+308` and values greater than `1.79769313486232e+308`
11874
    will be stored as NaN internally and be serialized to `null`.
11875
11876
    #### Storage
11877
11878
    Floating-point number values are stored directly inside a @ref basic_json
11879
    type.
11880
11881
    @sa @ref number_integer_t -- type for number values (integer)
11882
11883
    @sa @ref number_unsigned_t -- type for number values (unsigned integer)
11884
11885
    @since version 1.0.0
11886
    */
11887
    using number_float_t = NumberFloatType;
11888
11889
    /// @}
11890
11891
  private:
11892
11893
    /// helper for exception-safe object creation
11894
    template<typename T, typename... Args>
11895
    static T* create(Args&& ... args)
11896
151k
    {
11897
151k
        AllocatorType<T> alloc;
11898
151k
        using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
11899
151k
11900
151k
        auto deleter = [&](T * object)
11901
151k
        {
11902
0
            AllocatorTraits::deallocate(alloc, object, 1);
11903
0
        };
Unexecuted instantiation: _ZZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE6createIS1_IS8_SA_St4lessIvESaISt4pairIKS8_SA_EEEJEEEPT_DpOT0_ENKUlPSI_E_clESO_
Unexecuted instantiation: _ZZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE6createIS2_ISA_SaISA_EEJEEEPT_DpOT0_ENKUlPSD_E_clESJ_
Unexecuted instantiation: _ZZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE6createIS8_JRA1_KcEEEPT_DpOT0_ENKUlPS8_E_clESK_
Unexecuted instantiation: _ZZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE6createIS1_IS8_SA_St4lessIvESaISt4pairIKS8_SA_EEEJRKSI_EEEPT_DpOT0_ENKUlPSI_E_clESQ_
Unexecuted instantiation: _ZZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE6createIS2_ISA_SaISA_EEJRKSD_EEEPT_DpOT0_ENKUlPSD_E_clESL_
Unexecuted instantiation: _ZZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE6createIS8_JRKS8_EEEPT_DpOT0_ENKUlPS8_E_clESJ_
Unexecuted instantiation: _ZZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE6createIS8_JRA474_KcEEEPT_DpOT0_ENKUlPS8_E_clESK_
Unexecuted instantiation: _ZZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE6createIS8_JS8_EEEPT_DpOT0_ENKUlPS8_E_clESH_
Unexecuted instantiation: _ZZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE6createIS8_JRKPKcEEEPT_DpOT0_ENKUlPS8_E_clESL_
Unexecuted instantiation: _ZZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE6createIS8_JRA6_KcEEEPT_DpOT0_ENKUlPS8_E_clESK_
11904
151k
        std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
11905
151k
        AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
11906
151k
        assert(object != nullptr);
11907
151k
        return object.release();
11908
151k
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE6createIS1_IS8_SA_St4lessIvESaISt4pairIKS8_SA_EEEJEEEPT_DpOT0_
Line
Count
Source
11896
51.2k
    {
11897
51.2k
        AllocatorType<T> alloc;
11898
51.2k
        using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
11899
51.2k
11900
51.2k
        auto deleter = [&](T * object)
11901
51.2k
        {
11902
51.2k
            AllocatorTraits::deallocate(alloc, object, 1);
11903
51.2k
        };
11904
51.2k
        std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
11905
51.2k
        AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
11906
51.2k
        assert(object != nullptr);
11907
51.2k
        return object.release();
11908
51.2k
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE6createIS2_ISA_SaISA_EEJEEEPT_DpOT0_
Line
Count
Source
11896
601
    {
11897
601
        AllocatorType<T> alloc;
11898
601
        using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
11899
601
11900
601
        auto deleter = [&](T * object)
11901
601
        {
11902
601
            AllocatorTraits::deallocate(alloc, object, 1);
11903
601
        };
11904
601
        std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
11905
601
        AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
11906
601
        assert(object != nullptr);
11907
601
        return object.release();
11908
601
    }
Unexecuted instantiation: _ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE6createIS8_JRA1_KcEEEPT_DpOT0_
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE6createIS1_IS8_SA_St4lessIvESaISt4pairIKS8_SA_EEEJRKSI_EEEPT_DpOT0_
Line
Count
Source
11896
5.79k
    {
11897
5.79k
        AllocatorType<T> alloc;
11898
5.79k
        using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
11899
5.79k
11900
5.79k
        auto deleter = [&](T * object)
11901
5.79k
        {
11902
5.79k
            AllocatorTraits::deallocate(alloc, object, 1);
11903
5.79k
        };
11904
5.79k
        std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
11905
5.79k
        AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
11906
5.79k
        assert(object != nullptr);
11907
5.79k
        return object.release();
11908
5.79k
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE6createIS2_ISA_SaISA_EEJRKSD_EEEPT_DpOT0_
Line
Count
Source
11896
24
    {
11897
24
        AllocatorType<T> alloc;
11898
24
        using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
11899
24
11900
24
        auto deleter = [&](T * object)
11901
24
        {
11902
24
            AllocatorTraits::deallocate(alloc, object, 1);
11903
24
        };
11904
24
        std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
11905
24
        AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
11906
24
        assert(object != nullptr);
11907
24
        return object.release();
11908
24
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE6createIS8_JRKS8_EEEPT_DpOT0_
Line
Count
Source
11896
92.9k
    {
11897
92.9k
        AllocatorType<T> alloc;
11898
92.9k
        using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
11899
92.9k
11900
92.9k
        auto deleter = [&](T * object)
11901
92.9k
        {
11902
92.9k
            AllocatorTraits::deallocate(alloc, object, 1);
11903
92.9k
        };
11904
92.9k
        std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
11905
92.9k
        AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
11906
92.9k
        assert(object != nullptr);
11907
92.9k
        return object.release();
11908
92.9k
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE6createIS8_JRA474_KcEEEPT_DpOT0_
Line
Count
Source
11896
199
    {
11897
199
        AllocatorType<T> alloc;
11898
199
        using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
11899
199
11900
199
        auto deleter = [&](T * object)
11901
199
        {
11902
199
            AllocatorTraits::deallocate(alloc, object, 1);
11903
199
        };
11904
199
        std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
11905
199
        AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
11906
199
        assert(object != nullptr);
11907
199
        return object.release();
11908
199
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE6createIS8_JS8_EEEPT_DpOT0_
Line
Count
Source
11896
423
    {
11897
423
        AllocatorType<T> alloc;
11898
423
        using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
11899
423
11900
423
        auto deleter = [&](T * object)
11901
423
        {
11902
423
            AllocatorTraits::deallocate(alloc, object, 1);
11903
423
        };
11904
423
        std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
11905
423
        AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
11906
423
        assert(object != nullptr);
11907
423
        return object.release();
11908
423
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE6createIS8_JRKPKcEEEPT_DpOT0_
Line
Count
Source
11896
10
    {
11897
10
        AllocatorType<T> alloc;
11898
10
        using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
11899
10
11900
10
        auto deleter = [&](T * object)
11901
10
        {
11902
10
            AllocatorTraits::deallocate(alloc, object, 1);
11903
10
        };
11904
10
        std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
11905
10
        AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
11906
10
        assert(object != nullptr);
11907
10
        return object.release();
11908
10
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE6createIS8_JRA6_KcEEEPT_DpOT0_
Line
Count
Source
11896
1
    {
11897
1
        AllocatorType<T> alloc;
11898
1
        using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
11899
1
11900
1
        auto deleter = [&](T * object)
11901
1
        {
11902
1
            AllocatorTraits::deallocate(alloc, object, 1);
11903
1
        };
11904
1
        std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
11905
1
        AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
11906
1
        assert(object != nullptr);
11907
1
        return object.release();
11908
1
    }
11909
11910
    ////////////////////////
11911
    // JSON value storage //
11912
    ////////////////////////
11913
11914
    /*!
11915
    @brief a JSON value
11916
11917
    The actual storage for a JSON value of the @ref basic_json class. This
11918
    union combines the different storage types for the JSON value types
11919
    defined in @ref value_t.
11920
11921
    JSON type | value_t type    | used type
11922
    --------- | --------------- | ------------------------
11923
    object    | object          | pointer to @ref object_t
11924
    array     | array           | pointer to @ref array_t
11925
    string    | string          | pointer to @ref string_t
11926
    boolean   | boolean         | @ref boolean_t
11927
    number    | number_integer  | @ref number_integer_t
11928
    number    | number_unsigned | @ref number_unsigned_t
11929
    number    | number_float    | @ref number_float_t
11930
    null      | null            | *no value is stored*
11931
11932
    @note Variable-length types (objects, arrays, and strings) are stored as
11933
    pointers. The size of the union should not exceed 64 bits if the default
11934
    value types are used.
11935
11936
    @since version 1.0.0
11937
    */
11938
    union json_value
11939
    {
11940
        /// object (stored with pointer to save storage)
11941
        object_t* object;
11942
        /// array (stored with pointer to save storage)
11943
        array_t* array;
11944
        /// string (stored with pointer to save storage)
11945
        string_t* string;
11946
        /// boolean
11947
        boolean_t boolean;
11948
        /// number (integer)
11949
        number_integer_t number_integer;
11950
        /// number (unsigned integer)
11951
        number_unsigned_t number_unsigned;
11952
        /// number (floating-point)
11953
        number_float_t number_float;
11954
11955
        /// default constructor (for null values)
11956
        json_value() = default;
11957
        /// constructor for booleans
11958
615
        json_value(boolean_t v) noexcept : boolean(v) {}
11959
        /// constructor for numbers (integer)
11960
9.60k
        json_value(number_integer_t v) noexcept : number_integer(v) {}
11961
        /// constructor for numbers (unsigned)
11962
80.8k
        json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
11963
        /// constructor for numbers (floating-point)
11964
60.1k
        json_value(number_float_t v) noexcept : number_float(v) {}
11965
        /// constructor for empty values of a given type
11966
        json_value(value_t t)
11967
302k
        {
11968
302k
            switch (t)
11969
302k
            {
11970
302k
                case value_t::object:
11971
51.1k
                {
11972
51.1k
                    object = create<object_t>();
11973
51.1k
                    break;
11974
302k
                }
11975
302k
11976
302k
                case value_t::array:
11977
601
                {
11978
601
                    array = create<array_t>();
11979
601
                    break;
11980
302k
                }
11981
302k
11982
302k
                case value_t::string:
11983
0
                {
11984
0
                    string = create<string_t>("");
11985
0
                    break;
11986
302k
                }
11987
302k
11988
302k
                case value_t::boolean:
11989
0
                {
11990
0
                    boolean = boolean_t(false);
11991
0
                    break;
11992
302k
                }
11993
302k
11994
302k
                case value_t::number_integer:
11995
0
                {
11996
0
                    number_integer = number_integer_t(0);
11997
0
                    break;
11998
302k
                }
11999
302k
12000
302k
                case value_t::number_unsigned:
12001
0
                {
12002
0
                    number_unsigned = number_unsigned_t(0);
12003
0
                    break;
12004
302k
                }
12005
302k
12006
302k
                case value_t::number_float:
12007
0
                {
12008
0
                    number_float = number_float_t(0.0);
12009
0
                    break;
12010
302k
                }
12011
302k
12012
302k
                case value_t::null:
12013
251k
                {
12014
251k
                    object = nullptr;  // silence warning, see #821
12015
251k
                    break;
12016
302k
                }
12017
302k
12018
302k
                default:
12019
0
                {
12020
0
                    object = nullptr;  // silence warning, see #821
12021
0
                    if (JSON_UNLIKELY(t == value_t::null))
12022
0
                    {
12023
0
                        JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.2.0")); // LCOV_EXCL_LINE
12024
0
                    }
12025
0
                    break;
12026
0
                }
12027
302k
            }
12028
302k
        }
12029
12030
        /// constructor for strings
12031
        json_value(const string_t& value)
12032
92.9k
        {
12033
92.9k
            string = create<string_t>(value);
12034
92.9k
        }
12035
12036
        /// constructor for rvalue strings
12037
        json_value(string_t&& value)
12038
423
        {
12039
423
            string = create<string_t>(std::move(value));
12040
423
        }
12041
12042
        /// constructor for objects
12043
        json_value(const object_t& value)
12044
5.79k
        {
12045
5.79k
            object = create<object_t>(value);
12046
5.79k
        }
12047
12048
        /// constructor for rvalue objects
12049
        json_value(object_t&& value)
12050
        {
12051
            object = create<object_t>(std::move(value));
12052
        }
12053
12054
        /// constructor for arrays
12055
        json_value(const array_t& value)
12056
24
        {
12057
24
            array = create<array_t>(value);
12058
24
        }
12059
12060
        /// constructor for rvalue arrays
12061
        json_value(array_t&& value)
12062
        {
12063
            array = create<array_t>(std::move(value));
12064
        }
12065
12066
        void destroy(value_t t) noexcept
12067
565k
        {
12068
565k
            switch (t)
12069
565k
            {
12070
565k
                case value_t::object:
12071
57.0k
                {
12072
57.0k
                    AllocatorType<object_t> alloc;
12073
57.0k
                    std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
12074
57.0k
                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
12075
57.0k
                    break;
12076
565k
                }
12077
565k
12078
565k
                case value_t::array:
12079
625
                {
12080
625
                    AllocatorType<array_t> alloc;
12081
625
                    std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
12082
625
                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
12083
625
                    break;
12084
565k
                }
12085
565k
12086
565k
                case value_t::string:
12087
93.5k
                {
12088
93.5k
                    AllocatorType<string_t> alloc;
12089
93.5k
                    std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
12090
93.5k
                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
12091
93.5k
                    break;
12092
565k
                }
12093
565k
12094
565k
                default:
12095
414k
                {
12096
414k
                    break;
12097
565k
                }
12098
565k
            }
12099
565k
        }
12100
    };
12101
12102
    /*!
12103
    @brief checks the class invariants
12104
12105
    This function asserts the class invariants. It needs to be called at the
12106
    end of every constructor to make sure that created objects respect the
12107
    invariant. Furthermore, it has to be called each time the type of a JSON
12108
    value is changed, because the invariant expresses a relationship between
12109
    @a m_type and @a m_value.
12110
    */
12111
    void assert_invariant() const noexcept
12112
2.14M
    {
12113
2.14M
        assert(m_type != value_t::object or m_value.object != nullptr);
12114
2.14M
        assert(m_type != value_t::array or m_value.array != nullptr);
12115
2.14M
        assert(m_type != value_t::string or m_value.string != nullptr);
12116
2.14M
    }
12117
12118
  public:
12119
    //////////////////////////
12120
    // JSON parser callback //
12121
    //////////////////////////
12122
12123
    /*!
12124
    @brief parser event types
12125
12126
    The parser callback distinguishes the following events:
12127
    - `object_start`: the parser read `{` and started to process a JSON object
12128
    - `key`: the parser read a key of a value in an object
12129
    - `object_end`: the parser read `}` and finished processing a JSON object
12130
    - `array_start`: the parser read `[` and started to process a JSON array
12131
    - `array_end`: the parser read `]` and finished processing a JSON array
12132
    - `value`: the parser finished reading a JSON value
12133
12134
    @image html callback_events.png "Example when certain parse events are triggered"
12135
12136
    @sa @ref parser_callback_t for more information and examples
12137
    */
12138
    using parse_event_t = typename parser::parse_event_t;
12139
12140
    /*!
12141
    @brief per-element parser callback type
12142
12143
    With a parser callback function, the result of parsing a JSON text can be
12144
    influenced. When passed to @ref parse, it is called on certain events
12145
    (passed as @ref parse_event_t via parameter @a event) with a set recursion
12146
    depth @a depth and context JSON value @a parsed. The return value of the
12147
    callback function is a boolean indicating whether the element that emitted
12148
    the callback shall be kept or not.
12149
12150
    We distinguish six scenarios (determined by the event type) in which the
12151
    callback function can be called. The following table describes the values
12152
    of the parameters @a depth, @a event, and @a parsed.
12153
12154
    parameter @a event | description | parameter @a depth | parameter @a parsed
12155
    ------------------ | ----------- | ------------------ | -------------------
12156
    parse_event_t::object_start | the parser read `{` and started to process a JSON object | depth of the parent of the JSON object | a JSON value with type discarded
12157
    parse_event_t::key | the parser read a key of a value in an object | depth of the currently parsed JSON object | a JSON string containing the key
12158
    parse_event_t::object_end | the parser read `}` and finished processing a JSON object | depth of the parent of the JSON object | the parsed JSON object
12159
    parse_event_t::array_start | the parser read `[` and started to process a JSON array | depth of the parent of the JSON array | a JSON value with type discarded
12160
    parse_event_t::array_end | the parser read `]` and finished processing a JSON array | depth of the parent of the JSON array | the parsed JSON array
12161
    parse_event_t::value | the parser finished reading a JSON value | depth of the value | the parsed JSON value
12162
12163
    @image html callback_events.png "Example when certain parse events are triggered"
12164
12165
    Discarding a value (i.e., returning `false`) has different effects
12166
    depending on the context in which function was called:
12167
12168
    - Discarded values in structured types are skipped. That is, the parser
12169
      will behave as if the discarded value was never read.
12170
    - In case a value outside a structured type is skipped, it is replaced
12171
      with `null`. This case happens if the top-level element is skipped.
12172
12173
    @param[in] depth  the depth of the recursion during parsing
12174
12175
    @param[in] event  an event of type parse_event_t indicating the context in
12176
    the callback function has been called
12177
12178
    @param[in,out] parsed  the current intermediate parse result; note that
12179
    writing to this value has no effect for parse_event_t::key events
12180
12181
    @return Whether the JSON value which called the function during parsing
12182
    should be kept (`true`) or not (`false`). In the latter case, it is either
12183
    skipped completely or replaced by an empty discarded object.
12184
12185
    @sa @ref parse for examples
12186
12187
    @since version 1.0.0
12188
    */
12189
    using parser_callback_t = typename parser::parser_callback_t;
12190
12191
    //////////////////
12192
    // constructors //
12193
    //////////////////
12194
12195
    /// @name constructors and destructors
12196
    /// Constructors of class @ref basic_json, copy/move constructor, copy
12197
    /// assignment, static functions creating objects, and the destructor.
12198
    /// @{
12199
12200
    /*!
12201
    @brief create an empty value with a given type
12202
12203
    Create an empty JSON value with a given type. The value will be default
12204
    initialized with an empty value which depends on the type:
12205
12206
    Value type  | initial value
12207
    ----------- | -------------
12208
    null        | `null`
12209
    boolean     | `false`
12210
    string      | `""`
12211
    number      | `0`
12212
    object      | `{}`
12213
    array       | `[]`
12214
12215
    @param[in] v  the type of the value to create
12216
12217
    @complexity Constant.
12218
12219
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
12220
    changes to any JSON value.
12221
12222
    @liveexample{The following code shows the constructor for different @ref
12223
    value_t values,basic_json__value_t}
12224
12225
    @sa @ref clear() -- restores the postcondition of this constructor
12226
12227
    @since version 1.0.0
12228
    */
12229
    basic_json(const value_t v)
12230
        : m_type(v), m_value(v)
12231
302k
    {
12232
302k
        assert_invariant();
12233
302k
    }
12234
12235
    /*!
12236
    @brief create a null object
12237
12238
    Create a `null` JSON value. It either takes a null pointer as parameter
12239
    (explicitly creating `null`) or no parameter (implicitly creating `null`).
12240
    The passed null pointer itself is not read -- it is only used to choose
12241
    the right constructor.
12242
12243
    @complexity Constant.
12244
12245
    @exceptionsafety No-throw guarantee: this constructor never throws
12246
    exceptions.
12247
12248
    @liveexample{The following code shows the constructor with and without a
12249
    null pointer parameter.,basic_json__nullptr_t}
12250
12251
    @since version 1.0.0
12252
    */
12253
    basic_json(std::nullptr_t = nullptr) noexcept
12254
        : basic_json(value_t::null)
12255
251k
    {
12256
251k
        assert_invariant();
12257
251k
    }
12258
12259
    /*!
12260
    @brief create a JSON value
12261
12262
    This is a "catch all" constructor for all compatible JSON types; that is,
12263
    types for which a `to_json()` method exists. The constructor forwards the
12264
    parameter @a val to that method (to `json_serializer<U>::to_json` method
12265
    with `U = uncvref_t<CompatibleType>`, to be exact).
12266
12267
    Template type @a CompatibleType includes, but is not limited to, the
12268
    following types:
12269
    - **arrays**: @ref array_t and all kinds of compatible containers such as
12270
      `std::vector`, `std::deque`, `std::list`, `std::forward_list`,
12271
      `std::array`, `std::valarray`, `std::set`, `std::unordered_set`,
12272
      `std::multiset`, and `std::unordered_multiset` with a `value_type` from
12273
      which a @ref basic_json value can be constructed.
12274
    - **objects**: @ref object_t and all kinds of compatible associative
12275
      containers such as `std::map`, `std::unordered_map`, `std::multimap`,
12276
      and `std::unordered_multimap` with a `key_type` compatible to
12277
      @ref string_t and a `value_type` from which a @ref basic_json value can
12278
      be constructed.
12279
    - **strings**: @ref string_t, string literals, and all compatible string
12280
      containers can be used.
12281
    - **numbers**: @ref number_integer_t, @ref number_unsigned_t,
12282
      @ref number_float_t, and all convertible number types such as `int`,
12283
      `size_t`, `int64_t`, `float` or `double` can be used.
12284
    - **boolean**: @ref boolean_t / `bool` can be used.
12285
12286
    See the examples below.
12287
12288
    @tparam CompatibleType a type such that:
12289
    - @a CompatibleType is not derived from `std::istream`,
12290
    - @a CompatibleType is not @ref basic_json (to avoid hijacking copy/move
12291
         constructors),
12292
    - @a CompatibleType is not a different @ref basic_json type (i.e. with different template arguments)
12293
    - @a CompatibleType is not a @ref basic_json nested type (e.g.,
12294
         @ref json_pointer, @ref iterator, etc ...)
12295
    - @ref @ref json_serializer<U> has a
12296
         `to_json(basic_json_t&, CompatibleType&&)` method
12297
12298
    @tparam U = `uncvref_t<CompatibleType>`
12299
12300
    @param[in] val the value to be forwarded to the respective constructor
12301
12302
    @complexity Usually linear in the size of the passed @a val, also
12303
                depending on the implementation of the called `to_json()`
12304
                method.
12305
12306
    @exceptionsafety Depends on the called constructor. For types directly
12307
    supported by the library (i.e., all types for which no `to_json()` function
12308
    was provided), strong guarantee holds: if an exception is thrown, there are
12309
    no changes to any JSON value.
12310
12311
    @liveexample{The following code shows the constructor with several
12312
    compatible types.,basic_json__CompatibleType}
12313
12314
    @since version 2.1.0
12315
    */
12316
    template <typename CompatibleType,
12317
              typename U = detail::uncvref_t<CompatibleType>,
12318
              detail::enable_if_t<
12319
                  not detail::is_basic_json<U>::value and detail::is_compatible_type<basic_json_t, U>::value, int> = 0>
12320
    basic_json(CompatibleType && val) noexcept(noexcept(
12321
                JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
12322
                                           std::forward<CompatibleType>(val))))
12323
207k
    {
12324
207k
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
12325
207k
        assert_invariant();
12326
207k
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEC2IRS8_S8_Li0EEEOT_
Line
Count
Source
12323
62.5k
    {
12324
62.5k
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
12325
62.5k
        assert_invariant();
12326
62.5k
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEC2IRddLi0EEEOT_
Line
Count
Source
12323
57.4k
    {
12324
57.4k
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
12325
57.4k
        assert_invariant();
12326
57.4k
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEC2IRbbLi0EEEOT_
Line
Count
Source
12323
602
    {
12324
602
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
12325
602
        assert_invariant();
12326
602
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEC2IRllLi0EEEOT_
Line
Count
Source
12323
9.18k
    {
12324
9.18k
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
12325
9.18k
        assert_invariant();
12326
9.18k
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEC2IRmmLi0EEEOT_
Line
Count
Source
12323
77.0k
    {
12324
77.0k
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
12325
77.0k
        assert_invariant();
12326
77.0k
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEC2IRA474_KcA474_cLi0EEEOT_
Line
Count
Source
12323
199
    {
12324
199
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
12325
199
        assert_invariant();
12326
199
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEC2IS8_S8_Li0EEEOT_
Line
Count
Source
12323
423
    {
12324
423
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
12325
423
        assert_invariant();
12326
423
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEC2IKS8_S8_Li0EEEOT_
Line
Count
Source
12323
47
    {
12324
47
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
12325
47
        assert_invariant();
12326
47
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEC2IRjjLi0EEEOT_
Line
Count
Source
12323
141
    {
12324
141
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
12325
141
        assert_invariant();
12326
141
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEC2IRKPKcSD_Li0EEEOT_
Line
Count
Source
12323
10
    {
12324
10
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
12325
10
        assert_invariant();
12326
10
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEC2IbbLi0EEEOT_
Line
Count
Source
12323
1
    {
12324
1
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
12325
1
        assert_invariant();
12326
1
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEC2IddLi0EEEOT_
Line
Count
Source
12323
1
    {
12324
1
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
12325
1
        assert_invariant();
12326
1
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEC2IRA6_KcA6_cLi0EEEOT_
Line
Count
Source
12323
1
    {
12324
1
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
12325
1
        assert_invariant();
12326
1
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEC2IiiLi0EEEOT_
Line
Count
Source
12323
1
    {
12324
1
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
12325
1
        assert_invariant();
12326
1
    }
12327
12328
    /*!
12329
    @brief create a JSON value from an existing one
12330
12331
    This is a constructor for existing @ref basic_json types.
12332
    It does not hijack copy/move constructors, since the parameter has different
12333
    template arguments than the current ones.
12334
12335
    The constructor tries to convert the internal @ref m_value of the parameter.
12336
12337
    @tparam BasicJsonType a type such that:
12338
    - @a BasicJsonType is a @ref basic_json type.
12339
    - @a BasicJsonType has different template arguments than @ref basic_json_t.
12340
12341
    @param[in] val the @ref basic_json value to be converted.
12342
12343
    @complexity Usually linear in the size of the passed @a val, also
12344
                depending on the implementation of the called `to_json()`
12345
                method.
12346
12347
    @exceptionsafety Depends on the called constructor. For types directly
12348
    supported by the library (i.e., all types for which no `to_json()` function
12349
    was provided), strong guarantee holds: if an exception is thrown, there are
12350
    no changes to any JSON value.
12351
12352
    @since version 3.2.0
12353
    */
12354
    template <typename BasicJsonType,
12355
              detail::enable_if_t<
12356
                  detail::is_basic_json<BasicJsonType>::value and not std::is_same<basic_json, BasicJsonType>::value, int> = 0>
12357
    basic_json(const BasicJsonType& val)
12358
    {
12359
        using other_boolean_t = typename BasicJsonType::boolean_t;
12360
        using other_number_float_t = typename BasicJsonType::number_float_t;
12361
        using other_number_integer_t = typename BasicJsonType::number_integer_t;
12362
        using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
12363
        using other_string_t = typename BasicJsonType::string_t;
12364
        using other_object_t = typename BasicJsonType::object_t;
12365
        using other_array_t = typename BasicJsonType::array_t;
12366
12367
        switch (val.type())
12368
        {
12369
            case value_t::boolean:
12370
                JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
12371
                break;
12372
            case value_t::number_float:
12373
                JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
12374
                break;
12375
            case value_t::number_integer:
12376
                JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
12377
                break;
12378
            case value_t::number_unsigned:
12379
                JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
12380
                break;
12381
            case value_t::string:
12382
                JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
12383
                break;
12384
            case value_t::object:
12385
                JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
12386
                break;
12387
            case value_t::array:
12388
                JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
12389
                break;
12390
            case value_t::null:
12391
                *this = nullptr;
12392
                break;
12393
            case value_t::discarded:
12394
                m_type = value_t::discarded;
12395
                break;
12396
        }
12397
        assert_invariant();
12398
    }
12399
12400
    /*!
12401
    @brief create a container (array or object) from an initializer list
12402
12403
    Creates a JSON value of type array or object from the passed initializer
12404
    list @a init. In case @a type_deduction is `true` (default), the type of
12405
    the JSON value to be created is deducted from the initializer list @a init
12406
    according to the following rules:
12407
12408
    1. If the list is empty, an empty JSON object value `{}` is created.
12409
    2. If the list consists of pairs whose first element is a string, a JSON
12410
       object value is created where the first elements of the pairs are
12411
       treated as keys and the second elements are as values.
12412
    3. In all other cases, an array is created.
12413
12414
    The rules aim to create the best fit between a C++ initializer list and
12415
    JSON values. The rationale is as follows:
12416
12417
    1. The empty initializer list is written as `{}` which is exactly an empty
12418
       JSON object.
12419
    2. C++ has no way of describing mapped types other than to list a list of
12420
       pairs. As JSON requires that keys must be of type string, rule 2 is the
12421
       weakest constraint one can pose on initializer lists to interpret them
12422
       as an object.
12423
    3. In all other cases, the initializer list could not be interpreted as
12424
       JSON object type, so interpreting it as JSON array type is safe.
12425
12426
    With the rules described above, the following JSON values cannot be
12427
    expressed by an initializer list:
12428
12429
    - the empty array (`[]`): use @ref array(initializer_list_t)
12430
      with an empty initializer list in this case
12431
    - arrays whose elements satisfy rule 2: use @ref
12432
      array(initializer_list_t) with the same initializer list
12433
      in this case
12434
12435
    @note When used without parentheses around an empty initializer list, @ref
12436
    basic_json() is called instead of this function, yielding the JSON null
12437
    value.
12438
12439
    @param[in] init  initializer list with JSON values
12440
12441
    @param[in] type_deduction internal parameter; when set to `true`, the type
12442
    of the JSON value is deducted from the initializer list @a init; when set
12443
    to `false`, the type provided via @a manual_type is forced. This mode is
12444
    used by the functions @ref array(initializer_list_t) and
12445
    @ref object(initializer_list_t).
12446
12447
    @param[in] manual_type internal parameter; when @a type_deduction is set
12448
    to `false`, the created JSON value will use the provided type (only @ref
12449
    value_t::array and @ref value_t::object are valid); when @a type_deduction
12450
    is set to `true`, this parameter has no effect
12451
12452
    @throw type_error.301 if @a type_deduction is `false`, @a manual_type is
12453
    `value_t::object`, but @a init contains an element which is not a pair
12454
    whose first element is a string. In this case, the constructor could not
12455
    create an object. If @a type_deduction would have be `true`, an array
12456
    would have been created. See @ref object(initializer_list_t)
12457
    for an example.
12458
12459
    @complexity Linear in the size of the initializer list @a init.
12460
12461
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
12462
    changes to any JSON value.
12463
12464
    @liveexample{The example below shows how JSON values are created from
12465
    initializer lists.,basic_json__list_init_t}
12466
12467
    @sa @ref array(initializer_list_t) -- create a JSON array
12468
    value from an initializer list
12469
    @sa @ref object(initializer_list_t) -- create a JSON object
12470
    value from an initializer list
12471
12472
    @since version 1.0.0
12473
    */
12474
    basic_json(initializer_list_t init,
12475
               bool type_deduction = true,
12476
               value_t manual_type = value_t::array)
12477
    {
12478
        // check if each element is an array with two elements whose first
12479
        // element is a string
12480
        bool is_an_object = std::all_of(init.begin(), init.end(),
12481
                                        [](const detail::json_ref<basic_json>& element_ref)
12482
        {
12483
            return (element_ref->is_array() and element_ref->size() == 2 and (*element_ref)[0].is_string());
12484
        });
12485
12486
        // adjust type if type deduction is not wanted
12487
        if (not type_deduction)
12488
        {
12489
            // if array is wanted, do not create an object though possible
12490
            if (manual_type == value_t::array)
12491
            {
12492
                is_an_object = false;
12493
            }
12494
12495
            // if object is wanted but impossible, throw an exception
12496
            if (JSON_UNLIKELY(manual_type == value_t::object and not is_an_object))
12497
            {
12498
                JSON_THROW(type_error::create(301, "cannot create object from initializer list"));
12499
            }
12500
        }
12501
12502
        if (is_an_object)
12503
        {
12504
            // the initializer list is a list of pairs -> create object
12505
            m_type = value_t::object;
12506
            m_value = value_t::object;
12507
12508
            std::for_each(init.begin(), init.end(), [this](const detail::json_ref<basic_json>& element_ref)
12509
            {
12510
                auto element = element_ref.moved_or_copied();
12511
                m_value.object->emplace(
12512
                    std::move(*((*element.m_value.array)[0].m_value.string)),
12513
                    std::move((*element.m_value.array)[1]));
12514
            });
12515
        }
12516
        else
12517
        {
12518
            // the initializer list describes an array -> create array
12519
            m_type = value_t::array;
12520
            m_value.array = create<array_t>(init.begin(), init.end());
12521
        }
12522
12523
        assert_invariant();
12524
    }
12525
12526
    /*!
12527
    @brief explicitly create an array from an initializer list
12528
12529
    Creates a JSON array value from a given initializer list. That is, given a
12530
    list of values `a, b, c`, creates the JSON value `[a, b, c]`. If the
12531
    initializer list is empty, the empty array `[]` is created.
12532
12533
    @note This function is only needed to express two edge cases that cannot
12534
    be realized with the initializer list constructor (@ref
12535
    basic_json(initializer_list_t, bool, value_t)). These cases
12536
    are:
12537
    1. creating an array whose elements are all pairs whose first element is a
12538
    string -- in this case, the initializer list constructor would create an
12539
    object, taking the first elements as keys
12540
    2. creating an empty array -- passing the empty initializer list to the
12541
    initializer list constructor yields an empty object
12542
12543
    @param[in] init  initializer list with JSON values to create an array from
12544
    (optional)
12545
12546
    @return JSON array value
12547
12548
    @complexity Linear in the size of @a init.
12549
12550
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
12551
    changes to any JSON value.
12552
12553
    @liveexample{The following code shows an example for the `array`
12554
    function.,array}
12555
12556
    @sa @ref basic_json(initializer_list_t, bool, value_t) --
12557
    create a JSON value from an initializer list
12558
    @sa @ref object(initializer_list_t) -- create a JSON object
12559
    value from an initializer list
12560
12561
    @since version 1.0.0
12562
    */
12563
    static basic_json array(initializer_list_t init = {})
12564
    {
12565
        return basic_json(init, false, value_t::array);
12566
    }
12567
12568
    /*!
12569
    @brief explicitly create an object from an initializer list
12570
12571
    Creates a JSON object value from a given initializer list. The initializer
12572
    lists elements must be pairs, and their first elements must be strings. If
12573
    the initializer list is empty, the empty object `{}` is created.
12574
12575
    @note This function is only added for symmetry reasons. In contrast to the
12576
    related function @ref array(initializer_list_t), there are
12577
    no cases which can only be expressed by this function. That is, any
12578
    initializer list @a init can also be passed to the initializer list
12579
    constructor @ref basic_json(initializer_list_t, bool, value_t).
12580
12581
    @param[in] init  initializer list to create an object from (optional)
12582
12583
    @return JSON object value
12584
12585
    @throw type_error.301 if @a init is not a list of pairs whose first
12586
    elements are strings. In this case, no object can be created. When such a
12587
    value is passed to @ref basic_json(initializer_list_t, bool, value_t),
12588
    an array would have been created from the passed initializer list @a init.
12589
    See example below.
12590
12591
    @complexity Linear in the size of @a init.
12592
12593
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
12594
    changes to any JSON value.
12595
12596
    @liveexample{The following code shows an example for the `object`
12597
    function.,object}
12598
12599
    @sa @ref basic_json(initializer_list_t, bool, value_t) --
12600
    create a JSON value from an initializer list
12601
    @sa @ref array(initializer_list_t) -- create a JSON array
12602
    value from an initializer list
12603
12604
    @since version 1.0.0
12605
    */
12606
    static basic_json object(initializer_list_t init = {})
12607
    {
12608
        return basic_json(init, false, value_t::object);
12609
    }
12610
12611
    /*!
12612
    @brief construct an array with count copies of given value
12613
12614
    Constructs a JSON array value by creating @a cnt copies of a passed value.
12615
    In case @a cnt is `0`, an empty array is created.
12616
12617
    @param[in] cnt  the number of JSON copies of @a val to create
12618
    @param[in] val  the JSON value to copy
12619
12620
    @post `std::distance(begin(),end()) == cnt` holds.
12621
12622
    @complexity Linear in @a cnt.
12623
12624
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
12625
    changes to any JSON value.
12626
12627
    @liveexample{The following code shows examples for the @ref
12628
    basic_json(size_type\, const basic_json&)
12629
    constructor.,basic_json__size_type_basic_json}
12630
12631
    @since version 1.0.0
12632
    */
12633
    basic_json(size_type cnt, const basic_json& val)
12634
        : m_type(value_t::array)
12635
    {
12636
        m_value.array = create<array_t>(cnt, val);
12637
        assert_invariant();
12638
    }
12639
12640
    /*!
12641
    @brief construct a JSON container given an iterator range
12642
12643
    Constructs the JSON value with the contents of the range `[first, last)`.
12644
    The semantics depends on the different types a JSON value can have:
12645
    - In case of a null type, invalid_iterator.206 is thrown.
12646
    - In case of other primitive types (number, boolean, or string), @a first
12647
      must be `begin()` and @a last must be `end()`. In this case, the value is
12648
      copied. Otherwise, invalid_iterator.204 is thrown.
12649
    - In case of structured types (array, object), the constructor behaves as
12650
      similar versions for `std::vector` or `std::map`; that is, a JSON array
12651
      or object is constructed from the values in the range.
12652
12653
    @tparam InputIT an input iterator type (@ref iterator or @ref
12654
    const_iterator)
12655
12656
    @param[in] first begin of the range to copy from (included)
12657
    @param[in] last end of the range to copy from (excluded)
12658
12659
    @pre Iterators @a first and @a last must be initialized. **This
12660
         precondition is enforced with an assertion (see warning).** If
12661
         assertions are switched off, a violation of this precondition yields
12662
         undefined behavior.
12663
12664
    @pre Range `[first, last)` is valid. Usually, this precondition cannot be
12665
         checked efficiently. Only certain edge cases are detected; see the
12666
         description of the exceptions below. A violation of this precondition
12667
         yields undefined behavior.
12668
12669
    @warning A precondition is enforced with a runtime assertion that will
12670
             result in calling `std::abort` if this precondition is not met.
12671
             Assertions can be disabled by defining `NDEBUG` at compile time.
12672
             See https://en.cppreference.com/w/cpp/error/assert for more
12673
             information.
12674
12675
    @throw invalid_iterator.201 if iterators @a first and @a last are not
12676
    compatible (i.e., do not belong to the same JSON value). In this case,
12677
    the range `[first, last)` is undefined.
12678
    @throw invalid_iterator.204 if iterators @a first and @a last belong to a
12679
    primitive type (number, boolean, or string), but @a first does not point
12680
    to the first element any more. In this case, the range `[first, last)` is
12681
    undefined. See example code below.
12682
    @throw invalid_iterator.206 if iterators @a first and @a last belong to a
12683
    null value. In this case, the range `[first, last)` is undefined.
12684
12685
    @complexity Linear in distance between @a first and @a last.
12686
12687
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
12688
    changes to any JSON value.
12689
12690
    @liveexample{The example below shows several ways to create JSON values by
12691
    specifying a subrange with iterators.,basic_json__InputIt_InputIt}
12692
12693
    @since version 1.0.0
12694
    */
12695
    template<class InputIT, typename std::enable_if<
12696
                 std::is_same<InputIT, typename basic_json_t::iterator>::value or
12697
                 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int>::type = 0>
12698
    basic_json(InputIT first, InputIT last)
12699
    {
12700
        assert(first.m_object != nullptr);
12701
        assert(last.m_object != nullptr);
12702
12703
        // make sure iterator fits the current value
12704
        if (JSON_UNLIKELY(first.m_object != last.m_object))
12705
        {
12706
            JSON_THROW(invalid_iterator::create(201, "iterators are not compatible"));
12707
        }
12708
12709
        // copy type from first iterator
12710
        m_type = first.m_object->m_type;
12711
12712
        // check if iterator range is complete for primitive values
12713
        switch (m_type)
12714
        {
12715
            case value_t::boolean:
12716
            case value_t::number_float:
12717
            case value_t::number_integer:
12718
            case value_t::number_unsigned:
12719
            case value_t::string:
12720
            {
12721
                if (JSON_UNLIKELY(not first.m_it.primitive_iterator.is_begin()
12722
                                  or not last.m_it.primitive_iterator.is_end()))
12723
                {
12724
                    JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
12725
                }
12726
                break;
12727
            }
12728
12729
            default:
12730
                break;
12731
        }
12732
12733
        switch (m_type)
12734
        {
12735
            case value_t::number_integer:
12736
            {
12737
                m_value.number_integer = first.m_object->m_value.number_integer;
12738
                break;
12739
            }
12740
12741
            case value_t::number_unsigned:
12742
            {
12743
                m_value.number_unsigned = first.m_object->m_value.number_unsigned;
12744
                break;
12745
            }
12746
12747
            case value_t::number_float:
12748
            {
12749
                m_value.number_float = first.m_object->m_value.number_float;
12750
                break;
12751
            }
12752
12753
            case value_t::boolean:
12754
            {
12755
                m_value.boolean = first.m_object->m_value.boolean;
12756
                break;
12757
            }
12758
12759
            case value_t::string:
12760
            {
12761
                m_value = *first.m_object->m_value.string;
12762
                break;
12763
            }
12764
12765
            case value_t::object:
12766
            {
12767
                m_value.object = create<object_t>(first.m_it.object_iterator,
12768
                                                  last.m_it.object_iterator);
12769
                break;
12770
            }
12771
12772
            case value_t::array:
12773
            {
12774
                m_value.array = create<array_t>(first.m_it.array_iterator,
12775
                                                last.m_it.array_iterator);
12776
                break;
12777
            }
12778
12779
            default:
12780
                JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " +
12781
                                                    std::string(first.m_object->type_name())));
12782
        }
12783
12784
        assert_invariant();
12785
    }
12786
12787
12788
    ///////////////////////////////////////
12789
    // other constructors and destructor //
12790
    ///////////////////////////////////////
12791
12792
    /// @private
12793
    basic_json(const detail::json_ref<basic_json>& ref)
12794
        : basic_json(ref.moved_or_copied())
12795
    {}
12796
12797
    /*!
12798
    @brief copy constructor
12799
12800
    Creates a copy of a given JSON value.
12801
12802
    @param[in] other  the JSON value to copy
12803
12804
    @post `*this == other`
12805
12806
    @complexity Linear in the size of @a other.
12807
12808
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
12809
    changes to any JSON value.
12810
12811
    @requirement This function helps `basic_json` satisfying the
12812
    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
12813
    requirements:
12814
    - The complexity is linear.
12815
    - As postcondition, it holds: `other == basic_json(other)`.
12816
12817
    @liveexample{The following code shows an example for the copy
12818
    constructor.,basic_json__basic_json}
12819
12820
    @since version 1.0.0
12821
    */
12822
    basic_json(const basic_json& other)
12823
        : m_type(other.m_type)
12824
42.8k
    {
12825
42.8k
        // check of passed value is valid
12826
42.8k
        other.assert_invariant();
12827
42.8k
12828
42.8k
        switch (m_type)
12829
42.8k
        {
12830
42.8k
            case value_t::object:
12831
5.79k
            {
12832
5.79k
                m_value = *other.m_value.object;
12833
5.79k
                break;
12834
42.8k
            }
12835
42.8k
12836
42.8k
            case value_t::array:
12837
24
            {
12838
24
                m_value = *other.m_value.array;
12839
24
                break;
12840
42.8k
            }
12841
42.8k
12842
42.8k
            case value_t::string:
12843
30.3k
            {
12844
30.3k
                m_value = *other.m_value.string;
12845
30.3k
                break;
12846
42.8k
            }
12847
42.8k
12848
42.8k
            case value_t::boolean:
12849
12
            {
12850
12
                m_value = other.m_value.boolean;
12851
12
                break;
12852
42.8k
            }
12853
42.8k
12854
42.8k
            case value_t::number_integer:
12855
421
            {
12856
421
                m_value = other.m_value.number_integer;
12857
421
                break;
12858
42.8k
            }
12859
42.8k
12860
42.8k
            case value_t::number_unsigned:
12861
3.66k
            {
12862
3.66k
                m_value = other.m_value.number_unsigned;
12863
3.66k
                break;
12864
42.8k
            }
12865
42.8k
12866
42.8k
            case value_t::number_float:
12867
2.62k
            {
12868
2.62k
                m_value = other.m_value.number_float;
12869
2.62k
                break;
12870
42.8k
            }
12871
42.8k
12872
42.8k
            default:
12873
8
                break;
12874
42.8k
        }
12875
42.8k
12876
42.8k
        assert_invariant();
12877
42.8k
    }
12878
12879
    /*!
12880
    @brief move constructor
12881
12882
    Move constructor. Constructs a JSON value with the contents of the given
12883
    value @a other using move semantics. It "steals" the resources from @a
12884
    other and leaves it as JSON null value.
12885
12886
    @param[in,out] other  value to move to this object
12887
12888
    @post `*this` has the same value as @a other before the call.
12889
    @post @a other is a JSON null value.
12890
12891
    @complexity Constant.
12892
12893
    @exceptionsafety No-throw guarantee: this constructor never throws
12894
    exceptions.
12895
12896
    @requirement This function helps `basic_json` satisfying the
12897
    [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible)
12898
    requirements.
12899
12900
    @liveexample{The code below shows the move constructor explicitly called
12901
    via std::move.,basic_json__moveconstructor}
12902
12903
    @since version 1.0.0
12904
    */
12905
    basic_json(basic_json&& other) noexcept
12906
        : m_type(std::move(other.m_type)),
12907
          m_value(std::move(other.m_value))
12908
12.3k
    {
12909
12.3k
        // check that passed value is valid
12910
12.3k
        other.assert_invariant();
12911
12.3k
12912
12.3k
        // invalidate payload
12913
12.3k
        other.m_type = value_t::null;
12914
12.3k
        other.m_value = {};
12915
12.3k
12916
12.3k
        assert_invariant();
12917
12.3k
    }
12918
12919
    /*!
12920
    @brief copy assignment
12921
12922
    Copy assignment operator. Copies a JSON value via the "copy and swap"
12923
    strategy: It is expressed in terms of the copy constructor, destructor,
12924
    and the `swap()` member function.
12925
12926
    @param[in] other  value to copy from
12927
12928
    @complexity Linear.
12929
12930
    @requirement This function helps `basic_json` satisfying the
12931
    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
12932
    requirements:
12933
    - The complexity is linear.
12934
12935
    @liveexample{The code below shows and example for the copy assignment. It
12936
    creates a copy of value `a` which is then swapped with `b`. Finally\, the
12937
    copy of `a` (which is the null value after the swap) is
12938
    destroyed.,basic_json__copyassignment}
12939
12940
    @since version 1.0.0
12941
    */
12942
    reference& operator=(basic_json other) noexcept (
12943
        std::is_nothrow_move_constructible<value_t>::value and
12944
        std::is_nothrow_move_assignable<value_t>::value and
12945
        std::is_nothrow_move_constructible<json_value>::value and
12946
        std::is_nothrow_move_assignable<json_value>::value
12947
    )
12948
250k
    {
12949
250k
        // check that passed value is valid
12950
250k
        other.assert_invariant();
12951
250k
12952
250k
        using std::swap;
12953
250k
        swap(m_type, other.m_type);
12954
250k
        swap(m_value, other.m_value);
12955
250k
12956
250k
        assert_invariant();
12957
250k
        return *this;
12958
250k
    }
12959
12960
    /*!
12961
    @brief destructor
12962
12963
    Destroys the JSON value and frees all allocated memory.
12964
12965
    @complexity Linear.
12966
12967
    @requirement This function helps `basic_json` satisfying the
12968
    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
12969
    requirements:
12970
    - The complexity is linear.
12971
    - All stored elements are destroyed and all memory is freed.
12972
12973
    @since version 1.0.0
12974
    */
12975
    ~basic_json() noexcept
12976
565k
    {
12977
565k
        assert_invariant();
12978
565k
        m_value.destroy(m_type);
12979
565k
    }
12980
12981
    /// @}
12982
12983
  public:
12984
    ///////////////////////
12985
    // object inspection //
12986
    ///////////////////////
12987
12988
    /// @name object inspection
12989
    /// Functions to inspect the type of a JSON value.
12990
    /// @{
12991
12992
    /*!
12993
    @brief serialization
12994
12995
    Serialization function for JSON values. The function tries to mimic
12996
    Python's `json.dumps()` function, and currently supports its @a indent
12997
    and @a ensure_ascii parameters.
12998
12999
    @param[in] indent If indent is nonnegative, then array elements and object
13000
    members will be pretty-printed with that indent level. An indent level of
13001
    `0` will only insert newlines. `-1` (the default) selects the most compact
13002
    representation.
13003
    @param[in] indent_char The character to use for indentation if @a indent is
13004
    greater than `0`. The default is ` ` (space).
13005
    @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters
13006
    in the output are escaped with `\uXXXX` sequences, and the result consists
13007
    of ASCII characters only.
13008
13009
    @return string containing the serialization of the JSON value
13010
13011
    @throw type_error.316 if a string stored inside the JSON value is not
13012
                          UTF-8 encoded
13013
13014
    @complexity Linear.
13015
13016
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
13017
    changes in the JSON value.
13018
13019
    @liveexample{The following example shows the effect of different @a indent\,
13020
    @a indent_char\, and @a ensure_ascii parameters to the result of the
13021
    serialization.,dump}
13022
13023
    @see https://docs.python.org/2/library/json.html#json.dump
13024
13025
    @since version 1.0.0; indentation character @a indent_char, option
13026
           @a ensure_ascii and exceptions added in version 3.0.0
13027
    */
13028
    string_t dump(const int indent = -1, const char indent_char = ' ',
13029
                  const bool ensure_ascii = false) const
13030
17
    {
13031
17
        string_t result;
13032
17
        serializer s(detail::output_adapter<char, string_t>(result), indent_char);
13033
17
13034
17
        if (indent >= 0)
13035
15
        {
13036
15
            s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
13037
15
        }
13038
2
        else
13039
2
        {
13040
2
            s.dump(*this, false, ensure_ascii, 0);
13041
2
        }
13042
17
13043
17
        return result;
13044
17
    }
13045
13046
    /*!
13047
    @brief return the type of the JSON value (explicit)
13048
13049
    Return the type of the JSON value as a value from the @ref value_t
13050
    enumeration.
13051
13052
    @return the type of the JSON value
13053
            Value type                | return value
13054
            ------------------------- | -------------------------
13055
            null                      | value_t::null
13056
            boolean                   | value_t::boolean
13057
            string                    | value_t::string
13058
            number (integer)          | value_t::number_integer
13059
            number (unsigned integer) | value_t::number_unsigned
13060
            number (floating-point)   | value_t::number_float
13061
            object                    | value_t::object
13062
            array                     | value_t::array
13063
            discarded                 | value_t::discarded
13064
13065
    @complexity Constant.
13066
13067
    @exceptionsafety No-throw guarantee: this member function never throws
13068
    exceptions.
13069
13070
    @liveexample{The following code exemplifies `type()` for all JSON
13071
    types.,type}
13072
13073
    @sa @ref operator value_t() -- return the type of the JSON value (implicit)
13074
    @sa @ref type_name() -- return the type as string
13075
13076
    @since version 1.0.0
13077
    */
13078
    constexpr value_t type() const noexcept
13079
20
    {
13080
20
        return m_type;
13081
20
    }
13082
13083
    /*!
13084
    @brief return whether type is primitive
13085
13086
    This function returns true if and only if the JSON type is primitive
13087
    (string, number, boolean, or null).
13088
13089
    @return `true` if type is primitive (string, number, boolean, or null),
13090
    `false` otherwise.
13091
13092
    @complexity Constant.
13093
13094
    @exceptionsafety No-throw guarantee: this member function never throws
13095
    exceptions.
13096
13097
    @liveexample{The following code exemplifies `is_primitive()` for all JSON
13098
    types.,is_primitive}
13099
13100
    @sa @ref is_structured() -- returns whether JSON value is structured
13101
    @sa @ref is_null() -- returns whether JSON value is `null`
13102
    @sa @ref is_string() -- returns whether JSON value is a string
13103
    @sa @ref is_boolean() -- returns whether JSON value is a boolean
13104
    @sa @ref is_number() -- returns whether JSON value is a number
13105
13106
    @since version 1.0.0
13107
    */
13108
    constexpr bool is_primitive() const noexcept
13109
    {
13110
        return is_null() or is_string() or is_boolean() or is_number();
13111
    }
13112
13113
    /*!
13114
    @brief return whether type is structured
13115
13116
    This function returns true if and only if the JSON type is structured
13117
    (array or object).
13118
13119
    @return `true` if type is structured (array or object), `false` otherwise.
13120
13121
    @complexity Constant.
13122
13123
    @exceptionsafety No-throw guarantee: this member function never throws
13124
    exceptions.
13125
13126
    @liveexample{The following code exemplifies `is_structured()` for all JSON
13127
    types.,is_structured}
13128
13129
    @sa @ref is_primitive() -- returns whether value is primitive
13130
    @sa @ref is_array() -- returns whether value is an array
13131
    @sa @ref is_object() -- returns whether value is an object
13132
13133
    @since version 1.0.0
13134
    */
13135
    constexpr bool is_structured() const noexcept
13136
    {
13137
        return is_array() or is_object();
13138
    }
13139
13140
    /*!
13141
    @brief return whether value is null
13142
13143
    This function returns true if and only if the JSON value is null.
13144
13145
    @return `true` if type is null, `false` otherwise.
13146
13147
    @complexity Constant.
13148
13149
    @exceptionsafety No-throw guarantee: this member function never throws
13150
    exceptions.
13151
13152
    @liveexample{The following code exemplifies `is_null()` for all JSON
13153
    types.,is_null}
13154
13155
    @since version 1.0.0
13156
    */
13157
    constexpr bool is_null() const noexcept
13158
1.62k
    {
13159
1.62k
        return (m_type == value_t::null);
13160
1.62k
    }
13161
13162
    /*!
13163
    @brief return whether value is a boolean
13164
13165
    This function returns true if and only if the JSON value is a boolean.
13166
13167
    @return `true` if type is boolean, `false` otherwise.
13168
13169
    @complexity Constant.
13170
13171
    @exceptionsafety No-throw guarantee: this member function never throws
13172
    exceptions.
13173
13174
    @liveexample{The following code exemplifies `is_boolean()` for all JSON
13175
    types.,is_boolean}
13176
13177
    @since version 1.0.0
13178
    */
13179
    constexpr bool is_boolean() const noexcept
13180
4
    {
13181
4
        return (m_type == value_t::boolean);
13182
4
    }
13183
13184
    /*!
13185
    @brief return whether value is a number
13186
13187
    This function returns true if and only if the JSON value is a number. This
13188
    includes both integer (signed and unsigned) and floating-point values.
13189
13190
    @return `true` if type is number (regardless whether integer, unsigned
13191
    integer or floating-type), `false` otherwise.
13192
13193
    @complexity Constant.
13194
13195
    @exceptionsafety No-throw guarantee: this member function never throws
13196
    exceptions.
13197
13198
    @liveexample{The following code exemplifies `is_number()` for all JSON
13199
    types.,is_number}
13200
13201
    @sa @ref is_number_integer() -- check if value is an integer or unsigned
13202
    integer number
13203
    @sa @ref is_number_unsigned() -- check if value is an unsigned integer
13204
    number
13205
    @sa @ref is_number_float() -- check if value is a floating-point number
13206
13207
    @since version 1.0.0
13208
    */
13209
    constexpr bool is_number() const noexcept
13210
    {
13211
        return is_number_integer() or is_number_float();
13212
    }
13213
13214
    /*!
13215
    @brief return whether value is an integer number
13216
13217
    This function returns true if and only if the JSON value is a signed or
13218
    unsigned integer number. This excludes floating-point values.
13219
13220
    @return `true` if type is an integer or unsigned integer number, `false`
13221
    otherwise.
13222
13223
    @complexity Constant.
13224
13225
    @exceptionsafety No-throw guarantee: this member function never throws
13226
    exceptions.
13227
13228
    @liveexample{The following code exemplifies `is_number_integer()` for all
13229
    JSON types.,is_number_integer}
13230
13231
    @sa @ref is_number() -- check if value is a number
13232
    @sa @ref is_number_unsigned() -- check if value is an unsigned integer
13233
    number
13234
    @sa @ref is_number_float() -- check if value is a floating-point number
13235
13236
    @since version 1.0.0
13237
    */
13238
    constexpr bool is_number_integer() const noexcept
13239
0
    {
13240
0
        return (m_type == value_t::number_integer or m_type == value_t::number_unsigned);
13241
0
    }
13242
13243
    /*!
13244
    @brief return whether value is an unsigned integer number
13245
13246
    This function returns true if and only if the JSON value is an unsigned
13247
    integer number. This excludes floating-point and signed integer values.
13248
13249
    @return `true` if type is an unsigned integer number, `false` otherwise.
13250
13251
    @complexity Constant.
13252
13253
    @exceptionsafety No-throw guarantee: this member function never throws
13254
    exceptions.
13255
13256
    @liveexample{The following code exemplifies `is_number_unsigned()` for all
13257
    JSON types.,is_number_unsigned}
13258
13259
    @sa @ref is_number() -- check if value is a number
13260
    @sa @ref is_number_integer() -- check if value is an integer or unsigned
13261
    integer number
13262
    @sa @ref is_number_float() -- check if value is a floating-point number
13263
13264
    @since version 2.0.0
13265
    */
13266
    constexpr bool is_number_unsigned() const noexcept
13267
152
    {
13268
152
        return (m_type == value_t::number_unsigned);
13269
152
    }
13270
13271
    /*!
13272
    @brief return whether value is a floating-point number
13273
13274
    This function returns true if and only if the JSON value is a
13275
    floating-point number. This excludes signed and unsigned integer values.
13276
13277
    @return `true` if type is a floating-point number, `false` otherwise.
13278
13279
    @complexity Constant.
13280
13281
    @exceptionsafety No-throw guarantee: this member function never throws
13282
    exceptions.
13283
13284
    @liveexample{The following code exemplifies `is_number_float()` for all
13285
    JSON types.,is_number_float}
13286
13287
    @sa @ref is_number() -- check if value is number
13288
    @sa @ref is_number_integer() -- check if value is an integer number
13289
    @sa @ref is_number_unsigned() -- check if value is an unsigned integer
13290
    number
13291
13292
    @since version 1.0.0
13293
    */
13294
    constexpr bool is_number_float() const noexcept
13295
148
    {
13296
148
        return (m_type == value_t::number_float);
13297
148
    }
13298
13299
    /*!
13300
    @brief return whether value is an object
13301
13302
    This function returns true if and only if the JSON value is an object.
13303
13304
    @return `true` if type is object, `false` otherwise.
13305
13306
    @complexity Constant.
13307
13308
    @exceptionsafety No-throw guarantee: this member function never throws
13309
    exceptions.
13310
13311
    @liveexample{The following code exemplifies `is_object()` for all JSON
13312
    types.,is_object}
13313
13314
    @since version 1.0.0
13315
    */
13316
    constexpr bool is_object() const noexcept
13317
261k
    {
13318
261k
        return (m_type == value_t::object);
13319
261k
    }
13320
13321
    /*!
13322
    @brief return whether value is an array
13323
13324
    This function returns true if and only if the JSON value is an array.
13325
13326
    @return `true` if type is array, `false` otherwise.
13327
13328
    @complexity Constant.
13329
13330
    @exceptionsafety No-throw guarantee: this member function never throws
13331
    exceptions.
13332
13333
    @liveexample{The following code exemplifies `is_array()` for all JSON
13334
    types.,is_array}
13335
13336
    @since version 1.0.0
13337
    */
13338
    constexpr bool is_array() const noexcept
13339
514k
    {
13340
514k
        return (m_type == value_t::array);
13341
514k
    }
13342
13343
    /*!
13344
    @brief return whether value is a string
13345
13346
    This function returns true if and only if the JSON value is a string.
13347
13348
    @return `true` if type is string, `false` otherwise.
13349
13350
    @complexity Constant.
13351
13352
    @exceptionsafety No-throw guarantee: this member function never throws
13353
    exceptions.
13354
13355
    @liveexample{The following code exemplifies `is_string()` for all JSON
13356
    types.,is_string}
13357
13358
    @since version 1.0.0
13359
    */
13360
    constexpr bool is_string() const noexcept
13361
22.8k
    {
13362
22.8k
        return (m_type == value_t::string);
13363
22.8k
    }
13364
13365
    /*!
13366
    @brief return whether value is discarded
13367
13368
    This function returns true if and only if the JSON value was discarded
13369
    during parsing with a callback function (see @ref parser_callback_t).
13370
13371
    @note This function will always be `false` for JSON values after parsing.
13372
    That is, discarded values can only occur during parsing, but will be
13373
    removed when inside a structured value or replaced by null in other cases.
13374
13375
    @return `true` if type is discarded, `false` otherwise.
13376
13377
    @complexity Constant.
13378
13379
    @exceptionsafety No-throw guarantee: this member function never throws
13380
    exceptions.
13381
13382
    @liveexample{The following code exemplifies `is_discarded()` for all JSON
13383
    types.,is_discarded}
13384
13385
    @since version 1.0.0
13386
    */
13387
    constexpr bool is_discarded() const noexcept
13388
0
    {
13389
0
        return (m_type == value_t::discarded);
13390
0
    }
13391
13392
    /*!
13393
    @brief return the type of the JSON value (implicit)
13394
13395
    Implicitly return the type of the JSON value as a value from the @ref
13396
    value_t enumeration.
13397
13398
    @return the type of the JSON value
13399
13400
    @complexity Constant.
13401
13402
    @exceptionsafety No-throw guarantee: this member function never throws
13403
    exceptions.
13404
13405
    @liveexample{The following code exemplifies the @ref value_t operator for
13406
    all JSON types.,operator__value_t}
13407
13408
    @sa @ref type() -- return the type of the JSON value (explicit)
13409
    @sa @ref type_name() -- return the type as string
13410
13411
    @since version 1.0.0
13412
    */
13413
    constexpr operator value_t() const noexcept
13414
300
    {
13415
300
        return m_type;
13416
300
    }
13417
13418
    /// @}
13419
13420
  private:
13421
    //////////////////
13422
    // value access //
13423
    //////////////////
13424
13425
    /// get a boolean (explicit)
13426
    boolean_t get_impl(boolean_t* /*unused*/) const
13427
    {
13428
        if (JSON_LIKELY(is_boolean()))
13429
        {
13430
            return m_value.boolean;
13431
        }
13432
13433
        JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name())));
13434
    }
13435
13436
    /// get a pointer to the value (object)
13437
    object_t* get_impl_ptr(object_t* /*unused*/) noexcept
13438
    {
13439
        return is_object() ? m_value.object : nullptr;
13440
    }
13441
13442
    /// get a pointer to the value (object)
13443
    constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
13444
    {
13445
        return is_object() ? m_value.object : nullptr;
13446
    }
13447
13448
    /// get a pointer to the value (array)
13449
    array_t* get_impl_ptr(array_t* /*unused*/) noexcept
13450
    {
13451
        return is_array() ? m_value.array : nullptr;
13452
    }
13453
13454
    /// get a pointer to the value (array)
13455
    constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
13456
    {
13457
        return is_array() ? m_value.array : nullptr;
13458
    }
13459
13460
    /// get a pointer to the value (string)
13461
    string_t* get_impl_ptr(string_t* /*unused*/) noexcept
13462
    {
13463
        return is_string() ? m_value.string : nullptr;
13464
    }
13465
13466
    /// get a pointer to the value (string)
13467
    constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
13468
11.4k
    {
13469
11.4k
        return is_string() ? m_value.string : nullptr;
13470
11.4k
    }
13471
13472
    /// get a pointer to the value (boolean)
13473
    boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
13474
    {
13475
        return is_boolean() ? &m_value.boolean : nullptr;
13476
    }
13477
13478
    /// get a pointer to the value (boolean)
13479
    constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
13480
2
    {
13481
2
        return is_boolean() ? &m_value.boolean : nullptr;
13482
2
    }
13483
13484
    /// get a pointer to the value (integer number)
13485
    number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
13486
    {
13487
        return is_number_integer() ? &m_value.number_integer : nullptr;
13488
    }
13489
13490
    /// get a pointer to the value (integer number)
13491
    constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
13492
0
    {
13493
0
        return is_number_integer() ? &m_value.number_integer : nullptr;
13494
0
    }
13495
13496
    /// get a pointer to the value (unsigned number)
13497
    number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
13498
    {
13499
        return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
13500
    }
13501
13502
    /// get a pointer to the value (unsigned number)
13503
    constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
13504
152
    {
13505
152
        return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
13506
152
    }
13507
13508
    /// get a pointer to the value (floating-point number)
13509
    number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
13510
    {
13511
        return is_number_float() ? &m_value.number_float : nullptr;
13512
    }
13513
13514
    /// get a pointer to the value (floating-point number)
13515
    constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
13516
148
    {
13517
148
        return is_number_float() ? &m_value.number_float : nullptr;
13518
148
    }
13519
13520
    /*!
13521
    @brief helper function to implement get_ref()
13522
13523
    This function helps to implement get_ref() without code duplication for
13524
    const and non-const overloads
13525
13526
    @tparam ThisType will be deduced as `basic_json` or `const basic_json`
13527
13528
    @throw type_error.303 if ReferenceType does not match underlying value
13529
    type of the current JSON
13530
    */
13531
    template<typename ReferenceType, typename ThisType>
13532
    static ReferenceType get_ref_impl(ThisType& obj)
13533
    {
13534
        // delegate the call to get_ptr<>()
13535
        auto ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
13536
13537
        if (JSON_LIKELY(ptr != nullptr))
13538
        {
13539
            return *ptr;
13540
        }
13541
13542
        JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name())));
13543
    }
13544
13545
  public:
13546
    /// @name value access
13547
    /// Direct access to the stored value of a JSON value.
13548
    /// @{
13549
13550
    /*!
13551
    @brief get special-case overload
13552
13553
    This overloads avoids a lot of template boilerplate, it can be seen as the
13554
    identity method
13555
13556
    @tparam BasicJsonType == @ref basic_json
13557
13558
    @return a copy of *this
13559
13560
    @complexity Constant.
13561
13562
    @since version 2.1.0
13563
    */
13564
    template<typename BasicJsonType, detail::enable_if_t<
13565
                 std::is_same<typename std::remove_const<BasicJsonType>::type, basic_json_t>::value,
13566
                 int> = 0>
13567
    basic_json get() const
13568
12
    {
13569
12
        return *this;
13570
12
    }
13571
13572
    /*!
13573
    @brief get special-case overload
13574
13575
    This overloads converts the current @ref basic_json in a different
13576
    @ref basic_json type
13577
13578
    @tparam BasicJsonType == @ref basic_json
13579
13580
    @return a copy of *this, converted into @tparam BasicJsonType
13581
13582
    @complexity Depending on the implementation of the called `from_json()`
13583
                method.
13584
13585
    @since version 3.2.0
13586
    */
13587
    template<typename BasicJsonType, detail::enable_if_t<
13588
                 not std::is_same<BasicJsonType, basic_json>::value and
13589
                 detail::is_basic_json<BasicJsonType>::value, int> = 0>
13590
    BasicJsonType get() const
13591
    {
13592
        return *this;
13593
    }
13594
13595
    /*!
13596
    @brief get a value (explicit)
13597
13598
    Explicit type conversion between the JSON value and a compatible value
13599
    which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
13600
    and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
13601
    The value is converted by calling the @ref json_serializer<ValueType>
13602
    `from_json()` method.
13603
13604
    The function is equivalent to executing
13605
    @code {.cpp}
13606
    ValueType ret;
13607
    JSONSerializer<ValueType>::from_json(*this, ret);
13608
    return ret;
13609
    @endcode
13610
13611
    This overloads is chosen if:
13612
    - @a ValueType is not @ref basic_json,
13613
    - @ref json_serializer<ValueType> has a `from_json()` method of the form
13614
      `void from_json(const basic_json&, ValueType&)`, and
13615
    - @ref json_serializer<ValueType> does not have a `from_json()` method of
13616
      the form `ValueType from_json(const basic_json&)`
13617
13618
    @tparam ValueTypeCV the provided value type
13619
    @tparam ValueType the returned value type
13620
13621
    @return copy of the JSON value, converted to @a ValueType
13622
13623
    @throw what @ref json_serializer<ValueType> `from_json()` method throws
13624
13625
    @liveexample{The example below shows several conversions from JSON values
13626
    to other types. There a few things to note: (1) Floating-point numbers can
13627
    be converted to integers\, (2) A JSON array can be converted to a standard
13628
    `std::vector<short>`\, (3) A JSON object can be converted to C++
13629
    associative containers such as `std::unordered_map<std::string\,
13630
    json>`.,get__ValueType_const}
13631
13632
    @since version 2.1.0
13633
    */
13634
    template<typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,
13635
             detail::enable_if_t <
13636
                 not detail::is_basic_json<ValueType>::value and
13637
                 detail::has_from_json<basic_json_t, ValueType>::value and
13638
                 not detail::has_non_default_from_json<basic_json_t, ValueType>::value,
13639
                 int> = 0>
13640
    ValueType get() const noexcept(noexcept(
13641
                                       JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
13642
11.7k
    {
13643
11.7k
        // we cannot static_assert on ValueTypeCV being non-const, because
13644
11.7k
        // there is support for get<const basic_json_t>(), which is why we
13645
11.7k
        // still need the uncvref
13646
11.7k
        static_assert(not std::is_reference<ValueTypeCV>::value,
13647
11.7k
                      "get() cannot be used with reference types, you might want to use get_ref()");
13648
11.7k
        static_assert(std::is_default_constructible<ValueType>::value,
13649
11.7k
                      "types must be DefaultConstructible when used with get()");
13650
11.7k
13651
11.7k
        ValueType ret;
13652
11.7k
        JSONSerializer<ValueType>::from_json(*this, ret);
13653
11.7k
        return ret;
13654
11.7k
    }
_ZNK8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE3getIbbLi0EEET0_v
Line
Count
Source
13642
2
    {
13643
2
        // we cannot static_assert on ValueTypeCV being non-const, because
13644
2
        // there is support for get<const basic_json_t>(), which is why we
13645
2
        // still need the uncvref
13646
2
        static_assert(not std::is_reference<ValueTypeCV>::value,
13647
2
                      "get() cannot be used with reference types, you might want to use get_ref()");
13648
2
        static_assert(std::is_default_constructible<ValueType>::value,
13649
2
                      "types must be DefaultConstructible when used with get()");
13650
2
13651
2
        ValueType ret;
13652
2
        JSONSerializer<ValueType>::from_json(*this, ret);
13653
2
        return ret;
13654
2
    }
_ZNK8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE3getIS8_S8_Li0EEET0_v
Line
Count
Source
13642
11.4k
    {
13643
11.4k
        // we cannot static_assert on ValueTypeCV being non-const, because
13644
11.4k
        // there is support for get<const basic_json_t>(), which is why we
13645
11.4k
        // still need the uncvref
13646
11.4k
        static_assert(not std::is_reference<ValueTypeCV>::value,
13647
11.4k
                      "get() cannot be used with reference types, you might want to use get_ref()");
13648
11.4k
        static_assert(std::is_default_constructible<ValueType>::value,
13649
11.4k
                      "types must be DefaultConstructible when used with get()");
13650
11.4k
13651
11.4k
        ValueType ret;
13652
11.4k
        JSONSerializer<ValueType>::from_json(*this, ret);
13653
11.4k
        return ret;
13654
11.4k
    }
_ZNK8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE3getIiiLi0EEET0_v
Line
Count
Source
13642
152
    {
13643
152
        // we cannot static_assert on ValueTypeCV being non-const, because
13644
152
        // there is support for get<const basic_json_t>(), which is why we
13645
152
        // still need the uncvref
13646
152
        static_assert(not std::is_reference<ValueTypeCV>::value,
13647
152
                      "get() cannot be used with reference types, you might want to use get_ref()");
13648
152
        static_assert(std::is_default_constructible<ValueType>::value,
13649
152
                      "types must be DefaultConstructible when used with get()");
13650
152
13651
152
        ValueType ret;
13652
152
        JSONSerializer<ValueType>::from_json(*this, ret);
13653
152
        return ret;
13654
152
    }
_ZNK8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE3getIddLi0EEET0_v
Line
Count
Source
13642
148
    {
13643
148
        // we cannot static_assert on ValueTypeCV being non-const, because
13644
148
        // there is support for get<const basic_json_t>(), which is why we
13645
148
        // still need the uncvref
13646
148
        static_assert(not std::is_reference<ValueTypeCV>::value,
13647
148
                      "get() cannot be used with reference types, you might want to use get_ref()");
13648
148
        static_assert(std::is_default_constructible<ValueType>::value,
13649
148
                      "types must be DefaultConstructible when used with get()");
13650
148
13651
148
        ValueType ret;
13652
148
        JSONSerializer<ValueType>::from_json(*this, ret);
13653
148
        return ret;
13654
148
    }
13655
13656
    /*!
13657
    @brief get a value (explicit); special case
13658
13659
    Explicit type conversion between the JSON value and a compatible value
13660
    which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
13661
    and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
13662
    The value is converted by calling the @ref json_serializer<ValueType>
13663
    `from_json()` method.
13664
13665
    The function is equivalent to executing
13666
    @code {.cpp}
13667
    return JSONSerializer<ValueTypeCV>::from_json(*this);
13668
    @endcode
13669
13670
    This overloads is chosen if:
13671
    - @a ValueType is not @ref basic_json and
13672
    - @ref json_serializer<ValueType> has a `from_json()` method of the form
13673
      `ValueType from_json(const basic_json&)`
13674
13675
    @note If @ref json_serializer<ValueType> has both overloads of
13676
    `from_json()`, this one is chosen.
13677
13678
    @tparam ValueTypeCV the provided value type
13679
    @tparam ValueType the returned value type
13680
13681
    @return copy of the JSON value, converted to @a ValueType
13682
13683
    @throw what @ref json_serializer<ValueType> `from_json()` method throws
13684
13685
    @since version 2.1.0
13686
    */
13687
    template<typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,
13688
             detail::enable_if_t<not std::is_same<basic_json_t, ValueType>::value and
13689
                                 detail::has_non_default_from_json<basic_json_t, ValueType>::value,
13690
                                 int> = 0>
13691
    ValueType get() const noexcept(noexcept(
13692
                                       JSONSerializer<ValueTypeCV>::from_json(std::declval<const basic_json_t&>())))
13693
    {
13694
        static_assert(not std::is_reference<ValueTypeCV>::value,
13695
                      "get() cannot be used with reference types, you might want to use get_ref()");
13696
        return JSONSerializer<ValueTypeCV>::from_json(*this);
13697
    }
13698
13699
    /*!
13700
    @brief get a pointer value (explicit)
13701
13702
    Explicit pointer access to the internally stored JSON value. No copies are
13703
    made.
13704
13705
    @warning The pointer becomes invalid if the underlying JSON object
13706
    changes.
13707
13708
    @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
13709
    object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
13710
    @ref number_unsigned_t, or @ref number_float_t.
13711
13712
    @return pointer to the internally stored JSON value if the requested
13713
    pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
13714
13715
    @complexity Constant.
13716
13717
    @liveexample{The example below shows how pointers to internal values of a
13718
    JSON value can be requested. Note that no type conversions are made and a
13719
    `nullptr` is returned if the value and the requested pointer type does not
13720
    match.,get__PointerType}
13721
13722
    @sa @ref get_ptr() for explicit pointer-member access
13723
13724
    @since version 1.0.0
13725
    */
13726
    template<typename PointerType, typename std::enable_if<
13727
                 std::is_pointer<PointerType>::value, int>::type = 0>
13728
    PointerType get() noexcept
13729
    {
13730
        // delegate the call to get_ptr
13731
        return get_ptr<PointerType>();
13732
    }
13733
13734
    /*!
13735
    @brief get a pointer value (explicit)
13736
    @copydoc get()
13737
    */
13738
    template<typename PointerType, typename std::enable_if<
13739
                 std::is_pointer<PointerType>::value, int>::type = 0>
13740
    constexpr const PointerType get() const noexcept
13741
    {
13742
        // delegate the call to get_ptr
13743
        return get_ptr<PointerType>();
13744
    }
13745
13746
    /*!
13747
    @brief get a pointer value (implicit)
13748
13749
    Implicit pointer access to the internally stored JSON value. No copies are
13750
    made.
13751
13752
    @warning Writing data to the pointee of the result yields an undefined
13753
    state.
13754
13755
    @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
13756
    object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
13757
    @ref number_unsigned_t, or @ref number_float_t. Enforced by a static
13758
    assertion.
13759
13760
    @return pointer to the internally stored JSON value if the requested
13761
    pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
13762
13763
    @complexity Constant.
13764
13765
    @liveexample{The example below shows how pointers to internal values of a
13766
    JSON value can be requested. Note that no type conversions are made and a
13767
    `nullptr` is returned if the value and the requested pointer type does not
13768
    match.,get_ptr}
13769
13770
    @since version 1.0.0
13771
    */
13772
    template<typename PointerType, typename std::enable_if<
13773
                 std::is_pointer<PointerType>::value, int>::type = 0>
13774
    PointerType get_ptr() noexcept
13775
    {
13776
        // get the type of the PointerType (remove pointer and const)
13777
        using pointee_t = typename std::remove_const<typename
13778
                          std::remove_pointer<typename
13779
                          std::remove_const<PointerType>::type>::type>::type;
13780
        // make sure the type matches the allowed types
13781
        static_assert(
13782
            std::is_same<object_t, pointee_t>::value
13783
            or std::is_same<array_t, pointee_t>::value
13784
            or std::is_same<string_t, pointee_t>::value
13785
            or std::is_same<boolean_t, pointee_t>::value
13786
            or std::is_same<number_integer_t, pointee_t>::value
13787
            or std::is_same<number_unsigned_t, pointee_t>::value
13788
            or std::is_same<number_float_t, pointee_t>::value
13789
            , "incompatible pointer type");
13790
13791
        // delegate the call to get_impl_ptr<>()
13792
        return get_impl_ptr(static_cast<PointerType>(nullptr));
13793
    }
13794
13795
    /*!
13796
    @brief get a pointer value (implicit)
13797
    @copydoc get_ptr()
13798
    */
13799
    template<typename PointerType, typename std::enable_if<
13800
                 std::is_pointer<PointerType>::value and
13801
                 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int>::type = 0>
13802
    constexpr const PointerType get_ptr() const noexcept
13803
11.7k
    {
13804
11.7k
        // get the type of the PointerType (remove pointer and const)
13805
11.7k
        using pointee_t = typename std::remove_const<typename
13806
11.7k
                          std::remove_pointer<typename
13807
11.7k
                          std::remove_const<PointerType>::type>::type>::type;
13808
11.7k
        // make sure the type matches the allowed types
13809
11.7k
        static_assert(
13810
11.7k
            std::is_same<object_t, pointee_t>::value
13811
11.7k
            or std::is_same<array_t, pointee_t>::value
13812
11.7k
            or std::is_same<string_t, pointee_t>::value
13813
11.7k
            or std::is_same<boolean_t, pointee_t>::value
13814
11.7k
            or std::is_same<number_integer_t, pointee_t>::value
13815
11.7k
            or std::is_same<number_unsigned_t, pointee_t>::value
13816
11.7k
            or std::is_same<number_float_t, pointee_t>::value
13817
11.7k
            , "incompatible pointer type");
13818
11.7k
13819
11.7k
        // delegate the call to get_impl_ptr<>() const
13820
11.7k
        return get_impl_ptr(static_cast<PointerType>(nullptr));
13821
11.7k
    }
_ZNK8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE7get_ptrIPKbLi0EEEKT_v
Line
Count
Source
13803
2
    {
13804
2
        // get the type of the PointerType (remove pointer and const)
13805
2
        using pointee_t = typename std::remove_const<typename
13806
2
                          std::remove_pointer<typename
13807
2
                          std::remove_const<PointerType>::type>::type>::type;
13808
2
        // make sure the type matches the allowed types
13809
2
        static_assert(
13810
2
            std::is_same<object_t, pointee_t>::value
13811
2
            or std::is_same<array_t, pointee_t>::value
13812
2
            or std::is_same<string_t, pointee_t>::value
13813
2
            or std::is_same<boolean_t, pointee_t>::value
13814
2
            or std::is_same<number_integer_t, pointee_t>::value
13815
2
            or std::is_same<number_unsigned_t, pointee_t>::value
13816
2
            or std::is_same<number_float_t, pointee_t>::value
13817
2
            , "incompatible pointer type");
13818
2
13819
2
        // delegate the call to get_impl_ptr<>() const
13820
2
        return get_impl_ptr(static_cast<PointerType>(nullptr));
13821
2
    }
_ZNK8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE7get_ptrIPKS8_Li0EEEKT_v
Line
Count
Source
13803
11.4k
    {
13804
11.4k
        // get the type of the PointerType (remove pointer and const)
13805
11.4k
        using pointee_t = typename std::remove_const<typename
13806
11.4k
                          std::remove_pointer<typename
13807
11.4k
                          std::remove_const<PointerType>::type>::type>::type;
13808
11.4k
        // make sure the type matches the allowed types
13809
11.4k
        static_assert(
13810
11.4k
            std::is_same<object_t, pointee_t>::value
13811
11.4k
            or std::is_same<array_t, pointee_t>::value
13812
11.4k
            or std::is_same<string_t, pointee_t>::value
13813
11.4k
            or std::is_same<boolean_t, pointee_t>::value
13814
11.4k
            or std::is_same<number_integer_t, pointee_t>::value
13815
11.4k
            or std::is_same<number_unsigned_t, pointee_t>::value
13816
11.4k
            or std::is_same<number_float_t, pointee_t>::value
13817
11.4k
            , "incompatible pointer type");
13818
11.4k
13819
11.4k
        // delegate the call to get_impl_ptr<>() const
13820
11.4k
        return get_impl_ptr(static_cast<PointerType>(nullptr));
13821
11.4k
    }
_ZNK8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE7get_ptrIPKmLi0EEEKT_v
Line
Count
Source
13803
152
    {
13804
152
        // get the type of the PointerType (remove pointer and const)
13805
152
        using pointee_t = typename std::remove_const<typename
13806
152
                          std::remove_pointer<typename
13807
152
                          std::remove_const<PointerType>::type>::type>::type;
13808
152
        // make sure the type matches the allowed types
13809
152
        static_assert(
13810
152
            std::is_same<object_t, pointee_t>::value
13811
152
            or std::is_same<array_t, pointee_t>::value
13812
152
            or std::is_same<string_t, pointee_t>::value
13813
152
            or std::is_same<boolean_t, pointee_t>::value
13814
152
            or std::is_same<number_integer_t, pointee_t>::value
13815
152
            or std::is_same<number_unsigned_t, pointee_t>::value
13816
152
            or std::is_same<number_float_t, pointee_t>::value
13817
152
            , "incompatible pointer type");
13818
152
13819
152
        // delegate the call to get_impl_ptr<>() const
13820
152
        return get_impl_ptr(static_cast<PointerType>(nullptr));
13821
152
    }
Unexecuted instantiation: _ZNK8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE7get_ptrIPKlLi0EEEKT_v
_ZNK8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE7get_ptrIPKdLi0EEEKT_v
Line
Count
Source
13803
148
    {
13804
148
        // get the type of the PointerType (remove pointer and const)
13805
148
        using pointee_t = typename std::remove_const<typename
13806
148
                          std::remove_pointer<typename
13807
148
                          std::remove_const<PointerType>::type>::type>::type;
13808
148
        // make sure the type matches the allowed types
13809
148
        static_assert(
13810
148
            std::is_same<object_t, pointee_t>::value
13811
148
            or std::is_same<array_t, pointee_t>::value
13812
148
            or std::is_same<string_t, pointee_t>::value
13813
148
            or std::is_same<boolean_t, pointee_t>::value
13814
148
            or std::is_same<number_integer_t, pointee_t>::value
13815
148
            or std::is_same<number_unsigned_t, pointee_t>::value
13816
148
            or std::is_same<number_float_t, pointee_t>::value
13817
148
            , "incompatible pointer type");
13818
148
13819
148
        // delegate the call to get_impl_ptr<>() const
13820
148
        return get_impl_ptr(static_cast<PointerType>(nullptr));
13821
148
    }
13822
13823
    /*!
13824
    @brief get a reference value (implicit)
13825
13826
    Implicit reference access to the internally stored JSON value. No copies
13827
    are made.
13828
13829
    @warning Writing data to the referee of the result yields an undefined
13830
    state.
13831
13832
    @tparam ReferenceType reference type; must be a reference to @ref array_t,
13833
    @ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or
13834
    @ref number_float_t. Enforced by static assertion.
13835
13836
    @return reference to the internally stored JSON value if the requested
13837
    reference type @a ReferenceType fits to the JSON value; throws
13838
    type_error.303 otherwise
13839
13840
    @throw type_error.303 in case passed type @a ReferenceType is incompatible
13841
    with the stored JSON value; see example below
13842
13843
    @complexity Constant.
13844
13845
    @liveexample{The example shows several calls to `get_ref()`.,get_ref}
13846
13847
    @since version 1.1.0
13848
    */
13849
    template<typename ReferenceType, typename std::enable_if<
13850
                 std::is_reference<ReferenceType>::value, int>::type = 0>
13851
    ReferenceType get_ref()
13852
    {
13853
        // delegate call to get_ref_impl
13854
        return get_ref_impl<ReferenceType>(*this);
13855
    }
13856
13857
    /*!
13858
    @brief get a reference value (implicit)
13859
    @copydoc get_ref()
13860
    */
13861
    template<typename ReferenceType, typename std::enable_if<
13862
                 std::is_reference<ReferenceType>::value and
13863
                 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int>::type = 0>
13864
    ReferenceType get_ref() const
13865
    {
13866
        // delegate call to get_ref_impl
13867
        return get_ref_impl<ReferenceType>(*this);
13868
    }
13869
13870
    /*!
13871
    @brief get a value (implicit)
13872
13873
    Implicit type conversion between the JSON value and a compatible value.
13874
    The call is realized by calling @ref get() const.
13875
13876
    @tparam ValueType non-pointer type compatible to the JSON value, for
13877
    instance `int` for JSON integer numbers, `bool` for JSON booleans, or
13878
    `std::vector` types for JSON arrays. The character type of @ref string_t
13879
    as well as an initializer list of this type is excluded to avoid
13880
    ambiguities as these types implicitly convert to `std::string`.
13881
13882
    @return copy of the JSON value, converted to type @a ValueType
13883
13884
    @throw type_error.302 in case passed type @a ValueType is incompatible
13885
    to the JSON value type (e.g., the JSON value is of type boolean, but a
13886
    string is requested); see example below
13887
13888
    @complexity Linear in the size of the JSON value.
13889
13890
    @liveexample{The example below shows several conversions from JSON values
13891
    to other types. There a few things to note: (1) Floating-point numbers can
13892
    be converted to integers\, (2) A JSON array can be converted to a standard
13893
    `std::vector<short>`\, (3) A JSON object can be converted to C++
13894
    associative containers such as `std::unordered_map<std::string\,
13895
    json>`.,operator__ValueType}
13896
13897
    @since version 1.0.0
13898
    */
13899
    template < typename ValueType, typename std::enable_if <
13900
                   not std::is_pointer<ValueType>::value and
13901
                   not std::is_same<ValueType, detail::json_ref<basic_json>>::value and
13902
                   not std::is_same<ValueType, typename string_t::value_type>::value and
13903
                   not detail::is_basic_json<ValueType>::value
13904
#ifndef _MSC_VER  // fix for issue #167 operator<< ambiguity under VS2015
13905
                   and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
13906
#if defined(JSON_HAS_CPP_17) && defined(_MSC_VER) and _MSC_VER <= 1914
13907
                   and not std::is_same<ValueType, typename std::string_view>::value
13908
#endif
13909
#endif
13910
                   , int >::type = 0 >
13911
    operator ValueType() const
13912
    {
13913
        // delegate the call to get<>() const
13914
        return get<ValueType>();
13915
    }
13916
13917
    /// @}
13918
13919
13920
    ////////////////////
13921
    // element access //
13922
    ////////////////////
13923
13924
    /// @name element access
13925
    /// Access to the JSON value.
13926
    /// @{
13927
13928
    /*!
13929
    @brief access specified array element with bounds checking
13930
13931
    Returns a reference to the element at specified location @a idx, with
13932
    bounds checking.
13933
13934
    @param[in] idx  index of the element to access
13935
13936
    @return reference to the element at index @a idx
13937
13938
    @throw type_error.304 if the JSON value is not an array; in this case,
13939
    calling `at` with an index makes no sense. See example below.
13940
    @throw out_of_range.401 if the index @a idx is out of range of the array;
13941
    that is, `idx >= size()`. See example below.
13942
13943
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
13944
    changes in the JSON value.
13945
13946
    @complexity Constant.
13947
13948
    @since version 1.0.0
13949
13950
    @liveexample{The example below shows how array elements can be read and
13951
    written using `at()`. It also demonstrates the different exceptions that
13952
    can be thrown.,at__size_type}
13953
    */
13954
    reference at(size_type idx)
13955
    {
13956
        // at only works for arrays
13957
        if (JSON_LIKELY(is_array()))
13958
        {
13959
            JSON_TRY
13960
            {
13961
                return m_value.array->at(idx);
13962
            }
13963
            JSON_CATCH (std::out_of_range&)
13964
            {
13965
                // create better exception explanation
13966
                JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
13967
            }
13968
        }
13969
        else
13970
        {
13971
            JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
13972
        }
13973
    }
13974
13975
    /*!
13976
    @brief access specified array element with bounds checking
13977
13978
    Returns a const reference to the element at specified location @a idx,
13979
    with bounds checking.
13980
13981
    @param[in] idx  index of the element to access
13982
13983
    @return const reference to the element at index @a idx
13984
13985
    @throw type_error.304 if the JSON value is not an array; in this case,
13986
    calling `at` with an index makes no sense. See example below.
13987
    @throw out_of_range.401 if the index @a idx is out of range of the array;
13988
    that is, `idx >= size()`. See example below.
13989
13990
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
13991
    changes in the JSON value.
13992
13993
    @complexity Constant.
13994
13995
    @since version 1.0.0
13996
13997
    @liveexample{The example below shows how array elements can be read using
13998
    `at()`. It also demonstrates the different exceptions that can be thrown.,
13999
    at__size_type_const}
14000
    */
14001
    const_reference at(size_type idx) const
14002
    {
14003
        // at only works for arrays
14004
        if (JSON_LIKELY(is_array()))
14005
        {
14006
            JSON_TRY
14007
            {
14008
                return m_value.array->at(idx);
14009
            }
14010
            JSON_CATCH (std::out_of_range&)
14011
            {
14012
                // create better exception explanation
14013
                JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
14014
            }
14015
        }
14016
        else
14017
        {
14018
            JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
14019
        }
14020
    }
14021
14022
    /*!
14023
    @brief access specified object element with bounds checking
14024
14025
    Returns a reference to the element at with specified key @a key, with
14026
    bounds checking.
14027
14028
    @param[in] key  key of the element to access
14029
14030
    @return reference to the element at key @a key
14031
14032
    @throw type_error.304 if the JSON value is not an object; in this case,
14033
    calling `at` with a key makes no sense. See example below.
14034
    @throw out_of_range.403 if the key @a key is is not stored in the object;
14035
    that is, `find(key) == end()`. See example below.
14036
14037
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
14038
    changes in the JSON value.
14039
14040
    @complexity Logarithmic in the size of the container.
14041
14042
    @sa @ref operator[](const typename object_t::key_type&) for unchecked
14043
    access by reference
14044
    @sa @ref value() for access by value with a default value
14045
14046
    @since version 1.0.0
14047
14048
    @liveexample{The example below shows how object elements can be read and
14049
    written using `at()`. It also demonstrates the different exceptions that
14050
    can be thrown.,at__object_t_key_type}
14051
    */
14052
    reference at(const typename object_t::key_type& key)
14053
12.6k
    {
14054
12.6k
        // at only works for objects
14055
12.6k
        if (JSON_LIKELY(is_object()))
14056
12.6k
        {
14057
12.6k
            JSON_TRY
14058
12.6k
            {
14059
12.6k
                return m_value.object->at(key);
14060
12.6k
            }
14061
1
            JSON_CATCH (std::out_of_range&)
14062
1
            {
14063
1
                // create better exception explanation
14064
1
                JSON_THROW(out_of_range::create(403, "key '" + key + "' not found"));
14065
1
            }
14066
0
        }
14067
0
        else
14068
0
        {
14069
0
            JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
14070
0
        }
14071
0
    }
14072
14073
    /*!
14074
    @brief access specified object element with bounds checking
14075
14076
    Returns a const reference to the element at with specified key @a key,
14077
    with bounds checking.
14078
14079
    @param[in] key  key of the element to access
14080
14081
    @return const reference to the element at key @a key
14082
14083
    @throw type_error.304 if the JSON value is not an object; in this case,
14084
    calling `at` with a key makes no sense. See example below.
14085
    @throw out_of_range.403 if the key @a key is is not stored in the object;
14086
    that is, `find(key) == end()`. See example below.
14087
14088
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
14089
    changes in the JSON value.
14090
14091
    @complexity Logarithmic in the size of the container.
14092
14093
    @sa @ref operator[](const typename object_t::key_type&) for unchecked
14094
    access by reference
14095
    @sa @ref value() for access by value with a default value
14096
14097
    @since version 1.0.0
14098
14099
    @liveexample{The example below shows how object elements can be read using
14100
    `at()`. It also demonstrates the different exceptions that can be thrown.,
14101
    at__object_t_key_type_const}
14102
    */
14103
    const_reference at(const typename object_t::key_type& key) const
14104
    {
14105
        // at only works for objects
14106
        if (JSON_LIKELY(is_object()))
14107
        {
14108
            JSON_TRY
14109
            {
14110
                return m_value.object->at(key);
14111
            }
14112
            JSON_CATCH (std::out_of_range&)
14113
            {
14114
                // create better exception explanation
14115
                JSON_THROW(out_of_range::create(403, "key '" + key + "' not found"));
14116
            }
14117
        }
14118
        else
14119
        {
14120
            JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
14121
        }
14122
    }
14123
14124
    /*!
14125
    @brief access specified array element
14126
14127
    Returns a reference to the element at specified location @a idx.
14128
14129
    @note If @a idx is beyond the range of the array (i.e., `idx >= size()`),
14130
    then the array is silently filled up with `null` values to make `idx` a
14131
    valid reference to the last stored element.
14132
14133
    @param[in] idx  index of the element to access
14134
14135
    @return reference to the element at index @a idx
14136
14137
    @throw type_error.305 if the JSON value is not an array or null; in that
14138
    cases, using the [] operator with an index makes no sense.
14139
14140
    @complexity Constant if @a idx is in the range of the array. Otherwise
14141
    linear in `idx - size()`.
14142
14143
    @liveexample{The example below shows how array elements can be read and
14144
    written using `[]` operator. Note the addition of `null`
14145
    values.,operatorarray__size_type}
14146
14147
    @since version 1.0.0
14148
    */
14149
    reference operator[](size_type idx)
14150
    {
14151
        // implicitly convert null value to an empty array
14152
        if (is_null())
14153
        {
14154
            m_type = value_t::array;
14155
            m_value.array = create<array_t>();
14156
            assert_invariant();
14157
        }
14158
14159
        // operator[] only works for arrays
14160
        if (JSON_LIKELY(is_array()))
14161
        {
14162
            // fill up array with null values if given idx is outside range
14163
            if (idx >= m_value.array->size())
14164
            {
14165
                m_value.array->insert(m_value.array->end(),
14166
                                      idx - m_value.array->size() + 1,
14167
                                      basic_json());
14168
            }
14169
14170
            return m_value.array->operator[](idx);
14171
        }
14172
14173
        JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name())));
14174
    }
14175
14176
    /*!
14177
    @brief access specified array element
14178
14179
    Returns a const reference to the element at specified location @a idx.
14180
14181
    @param[in] idx  index of the element to access
14182
14183
    @return const reference to the element at index @a idx
14184
14185
    @throw type_error.305 if the JSON value is not an array; in that case,
14186
    using the [] operator with an index makes no sense.
14187
14188
    @complexity Constant.
14189
14190
    @liveexample{The example below shows how array elements can be read using
14191
    the `[]` operator.,operatorarray__size_type_const}
14192
14193
    @since version 1.0.0
14194
    */
14195
    const_reference operator[](size_type idx) const
14196
    {
14197
        // const operator[] only works for arrays
14198
        if (JSON_LIKELY(is_array()))
14199
        {
14200
            return m_value.array->operator[](idx);
14201
        }
14202
14203
        JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name())));
14204
    }
14205
14206
    /*!
14207
    @brief access specified object element
14208
14209
    Returns a reference to the element at with specified key @a key.
14210
14211
    @note If @a key is not found in the object, then it is silently added to
14212
    the object and filled with a `null` value to make `key` a valid reference.
14213
    In case the value was `null` before, it is converted to an object.
14214
14215
    @param[in] key  key of the element to access
14216
14217
    @return reference to the element at key @a key
14218
14219
    @throw type_error.305 if the JSON value is not an object or null; in that
14220
    cases, using the [] operator with a key makes no sense.
14221
14222
    @complexity Logarithmic in the size of the container.
14223
14224
    @liveexample{The example below shows how object elements can be read and
14225
    written using the `[]` operator.,operatorarray__key_type}
14226
14227
    @sa @ref at(const typename object_t::key_type&) for access by reference
14228
    with range checking
14229
    @sa @ref value() for access by value with a default value
14230
14231
    @since version 1.0.0
14232
    */
14233
    reference operator[](const typename object_t::key_type& key)
14234
307
    {
14235
307
        // implicitly convert null value to an empty object
14236
307
        if (is_null())
14237
77
        {
14238
77
            m_type = value_t::object;
14239
77
            m_value.object = create<object_t>();
14240
77
            assert_invariant();
14241
77
        }
14242
307
14243
307
        // operator[] only works for objects
14244
307
        if (JSON_LIKELY(is_object()))
14245
307
        {
14246
307
            return m_value.object->operator[](key);
14247
307
        }
14248
0
14249
0
        JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
14250
0
    }
14251
14252
    /*!
14253
    @brief read-only access specified object element
14254
14255
    Returns a const reference to the element at with specified key @a key. No
14256
    bounds checking is performed.
14257
14258
    @warning If the element with key @a key does not exist, the behavior is
14259
    undefined.
14260
14261
    @param[in] key  key of the element to access
14262
14263
    @return const reference to the element at key @a key
14264
14265
    @pre The element with key @a key must exist. **This precondition is
14266
         enforced with an assertion.**
14267
14268
    @throw type_error.305 if the JSON value is not an object; in that case,
14269
    using the [] operator with a key makes no sense.
14270
14271
    @complexity Logarithmic in the size of the container.
14272
14273
    @liveexample{The example below shows how object elements can be read using
14274
    the `[]` operator.,operatorarray__key_type_const}
14275
14276
    @sa @ref at(const typename object_t::key_type&) for access by reference
14277
    with range checking
14278
    @sa @ref value() for access by value with a default value
14279
14280
    @since version 1.0.0
14281
    */
14282
    const_reference operator[](const typename object_t::key_type& key) const
14283
    {
14284
        // const operator[] only works for objects
14285
        if (JSON_LIKELY(is_object()))
14286
        {
14287
            assert(m_value.object->find(key) != m_value.object->end());
14288
            return m_value.object->find(key)->second;
14289
        }
14290
14291
        JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
14292
    }
14293
14294
    /*!
14295
    @brief access specified object element
14296
14297
    Returns a reference to the element at with specified key @a key.
14298
14299
    @note If @a key is not found in the object, then it is silently added to
14300
    the object and filled with a `null` value to make `key` a valid reference.
14301
    In case the value was `null` before, it is converted to an object.
14302
14303
    @param[in] key  key of the element to access
14304
14305
    @return reference to the element at key @a key
14306
14307
    @throw type_error.305 if the JSON value is not an object or null; in that
14308
    cases, using the [] operator with a key makes no sense.
14309
14310
    @complexity Logarithmic in the size of the container.
14311
14312
    @liveexample{The example below shows how object elements can be read and
14313
    written using the `[]` operator.,operatorarray__key_type}
14314
14315
    @sa @ref at(const typename object_t::key_type&) for access by reference
14316
    with range checking
14317
    @sa @ref value() for access by value with a default value
14318
14319
    @since version 1.1.0
14320
    */
14321
    template<typename T>
14322
    reference operator[](T* key)
14323
1.32k
    {
14324
1.32k
        // implicitly convert null to object
14325
1.32k
        if (is_null())
14326
267
        {
14327
267
            m_type = value_t::object;
14328
267
            m_value = value_t::object;
14329
267
            assert_invariant();
14330
267
        }
14331
1.32k
14332
1.32k
        // at only works for objects
14333
1.32k
        if (JSON_LIKELY(is_object()))
14334
1.32k
        {
14335
1.32k
            return m_value.object->operator[](key);
14336
1.32k
        }
14337
0
14338
0
        JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
14339
0
    }
14340
14341
    /*!
14342
    @brief read-only access specified object element
14343
14344
    Returns a const reference to the element at with specified key @a key. No
14345
    bounds checking is performed.
14346
14347
    @warning If the element with key @a key does not exist, the behavior is
14348
    undefined.
14349
14350
    @param[in] key  key of the element to access
14351
14352
    @return const reference to the element at key @a key
14353
14354
    @pre The element with key @a key must exist. **This precondition is
14355
         enforced with an assertion.**
14356
14357
    @throw type_error.305 if the JSON value is not an object; in that case,
14358
    using the [] operator with a key makes no sense.
14359
14360
    @complexity Logarithmic in the size of the container.
14361
14362
    @liveexample{The example below shows how object elements can be read using
14363
    the `[]` operator.,operatorarray__key_type_const}
14364
14365
    @sa @ref at(const typename object_t::key_type&) for access by reference
14366
    with range checking
14367
    @sa @ref value() for access by value with a default value
14368
14369
    @since version 1.1.0
14370
    */
14371
    template<typename T>
14372
    const_reference operator[](T* key) const
14373
    {
14374
        // at only works for objects
14375
        if (JSON_LIKELY(is_object()))
14376
        {
14377
            assert(m_value.object->find(key) != m_value.object->end());
14378
            return m_value.object->find(key)->second;
14379
        }
14380
14381
        JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
14382
    }
14383
14384
    /*!
14385
    @brief access specified object element with default value
14386
14387
    Returns either a copy of an object's element at the specified key @a key
14388
    or a given default value if no element with key @a key exists.
14389
14390
    The function is basically equivalent to executing
14391
    @code {.cpp}
14392
    try {
14393
        return at(key);
14394
    } catch(out_of_range) {
14395
        return default_value;
14396
    }
14397
    @endcode
14398
14399
    @note Unlike @ref at(const typename object_t::key_type&), this function
14400
    does not throw if the given key @a key was not found.
14401
14402
    @note Unlike @ref operator[](const typename object_t::key_type& key), this
14403
    function does not implicitly add an element to the position defined by @a
14404
    key. This function is furthermore also applicable to const objects.
14405
14406
    @param[in] key  key of the element to access
14407
    @param[in] default_value  the value to return if @a key is not found
14408
14409
    @tparam ValueType type compatible to JSON values, for instance `int` for
14410
    JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for
14411
    JSON arrays. Note the type of the expected value at @a key and the default
14412
    value @a default_value must be compatible.
14413
14414
    @return copy of the element at key @a key or @a default_value if @a key
14415
    is not found
14416
14417
    @throw type_error.306 if the JSON value is not an object; in that case,
14418
    using `value()` with a key makes no sense.
14419
14420
    @complexity Logarithmic in the size of the container.
14421
14422
    @liveexample{The example below shows how object elements can be queried
14423
    with a default value.,basic_json__value}
14424
14425
    @sa @ref at(const typename object_t::key_type&) for access by reference
14426
    with range checking
14427
    @sa @ref operator[](const typename object_t::key_type&) for unchecked
14428
    access by reference
14429
14430
    @since version 1.0.0
14431
    */
14432
    template<class ValueType, typename std::enable_if<
14433
                 std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
14434
    ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
14435
    {
14436
        // at only works for objects
14437
        if (JSON_LIKELY(is_object()))
14438
        {
14439
            // if key is found, return value and given default value otherwise
14440
            const auto it = find(key);
14441
            if (it != end())
14442
            {
14443
                return *it;
14444
            }
14445
14446
            return default_value;
14447
        }
14448
14449
        JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name())));
14450
    }
14451
14452
    /*!
14453
    @brief overload for a default value of type const char*
14454
    @copydoc basic_json::value(const typename object_t::key_type&, ValueType) const
14455
    */
14456
    string_t value(const typename object_t::key_type& key, const char* default_value) const
14457
    {
14458
        return value(key, string_t(default_value));
14459
    }
14460
14461
    /*!
14462
    @brief access specified object element via JSON Pointer with default value
14463
14464
    Returns either a copy of an object's element at the specified key @a key
14465
    or a given default value if no element with key @a key exists.
14466
14467
    The function is basically equivalent to executing
14468
    @code {.cpp}
14469
    try {
14470
        return at(ptr);
14471
    } catch(out_of_range) {
14472
        return default_value;
14473
    }
14474
    @endcode
14475
14476
    @note Unlike @ref at(const json_pointer&), this function does not throw
14477
    if the given key @a key was not found.
14478
14479
    @param[in] ptr  a JSON pointer to the element to access
14480
    @param[in] default_value  the value to return if @a ptr found no value
14481
14482
    @tparam ValueType type compatible to JSON values, for instance `int` for
14483
    JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for
14484
    JSON arrays. Note the type of the expected value at @a key and the default
14485
    value @a default_value must be compatible.
14486
14487
    @return copy of the element at key @a key or @a default_value if @a key
14488
    is not found
14489
14490
    @throw type_error.306 if the JSON value is not an object; in that case,
14491
    using `value()` with a key makes no sense.
14492
14493
    @complexity Logarithmic in the size of the container.
14494
14495
    @liveexample{The example below shows how object elements can be queried
14496
    with a default value.,basic_json__value_ptr}
14497
14498
    @sa @ref operator[](const json_pointer&) for unchecked access by reference
14499
14500
    @since version 2.0.2
14501
    */
14502
    template<class ValueType, typename std::enable_if<
14503
                 std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
14504
    ValueType value(const json_pointer& ptr, const ValueType& default_value) const
14505
    {
14506
        // at only works for objects
14507
        if (JSON_LIKELY(is_object()))
14508
        {
14509
            // if pointer resolves a value, return it or use default value
14510
            JSON_TRY
14511
            {
14512
                return ptr.get_checked(this);
14513
            }
14514
            JSON_INTERNAL_CATCH (out_of_range&)
14515
            {
14516
                return default_value;
14517
            }
14518
        }
14519
14520
        JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name())));
14521
    }
14522
14523
    /*!
14524
    @brief overload for a default value of type const char*
14525
    @copydoc basic_json::value(const json_pointer&, ValueType) const
14526
    */
14527
    string_t value(const json_pointer& ptr, const char* default_value) const
14528
    {
14529
        return value(ptr, string_t(default_value));
14530
    }
14531
14532
    /*!
14533
    @brief access the first element
14534
14535
    Returns a reference to the first element in the container. For a JSON
14536
    container `c`, the expression `c.front()` is equivalent to `*c.begin()`.
14537
14538
    @return In case of a structured type (array or object), a reference to the
14539
    first element is returned. In case of number, string, or boolean values, a
14540
    reference to the value is returned.
14541
14542
    @complexity Constant.
14543
14544
    @pre The JSON value must not be `null` (would throw `std::out_of_range`)
14545
    or an empty array or object (undefined behavior, **guarded by
14546
    assertions**).
14547
    @post The JSON value remains unchanged.
14548
14549
    @throw invalid_iterator.214 when called on `null` value
14550
14551
    @liveexample{The following code shows an example for `front()`.,front}
14552
14553
    @sa @ref back() -- access the last element
14554
14555
    @since version 1.0.0
14556
    */
14557
    reference front()
14558
    {
14559
        return *begin();
14560
    }
14561
14562
    /*!
14563
    @copydoc basic_json::front()
14564
    */
14565
    const_reference front() const
14566
    {
14567
        return *cbegin();
14568
    }
14569
14570
    /*!
14571
    @brief access the last element
14572
14573
    Returns a reference to the last element in the container. For a JSON
14574
    container `c`, the expression `c.back()` is equivalent to
14575
    @code {.cpp}
14576
    auto tmp = c.end();
14577
    --tmp;
14578
    return *tmp;
14579
    @endcode
14580
14581
    @return In case of a structured type (array or object), a reference to the
14582
    last element is returned. In case of number, string, or boolean values, a
14583
    reference to the value is returned.
14584
14585
    @complexity Constant.
14586
14587
    @pre The JSON value must not be `null` (would throw `std::out_of_range`)
14588
    or an empty array or object (undefined behavior, **guarded by
14589
    assertions**).
14590
    @post The JSON value remains unchanged.
14591
14592
    @throw invalid_iterator.214 when called on a `null` value. See example
14593
    below.
14594
14595
    @liveexample{The following code shows an example for `back()`.,back}
14596
14597
    @sa @ref front() -- access the first element
14598
14599
    @since version 1.0.0
14600
    */
14601
    reference back()
14602
    {
14603
        auto tmp = end();
14604
        --tmp;
14605
        return *tmp;
14606
    }
14607
14608
    /*!
14609
    @copydoc basic_json::back()
14610
    */
14611
    const_reference back() const
14612
    {
14613
        auto tmp = cend();
14614
        --tmp;
14615
        return *tmp;
14616
    }
14617
14618
    /*!
14619
    @brief remove element given an iterator
14620
14621
    Removes the element specified by iterator @a pos. The iterator @a pos must
14622
    be valid and dereferenceable. Thus the `end()` iterator (which is valid,
14623
    but is not dereferenceable) cannot be used as a value for @a pos.
14624
14625
    If called on a primitive type other than `null`, the resulting JSON value
14626
    will be `null`.
14627
14628
    @param[in] pos iterator to the element to remove
14629
    @return Iterator following the last removed element. If the iterator @a
14630
    pos refers to the last element, the `end()` iterator is returned.
14631
14632
    @tparam IteratorType an @ref iterator or @ref const_iterator
14633
14634
    @post Invalidates iterators and references at or after the point of the
14635
    erase, including the `end()` iterator.
14636
14637
    @throw type_error.307 if called on a `null` value; example: `"cannot use
14638
    erase() with null"`
14639
    @throw invalid_iterator.202 if called on an iterator which does not belong
14640
    to the current JSON value; example: `"iterator does not fit current
14641
    value"`
14642
    @throw invalid_iterator.205 if called on a primitive type with invalid
14643
    iterator (i.e., any iterator which is not `begin()`); example: `"iterator
14644
    out of range"`
14645
14646
    @complexity The complexity depends on the type:
14647
    - objects: amortized constant
14648
    - arrays: linear in distance between @a pos and the end of the container
14649
    - strings: linear in the length of the string
14650
    - other types: constant
14651
14652
    @liveexample{The example shows the result of `erase()` for different JSON
14653
    types.,erase__IteratorType}
14654
14655
    @sa @ref erase(IteratorType, IteratorType) -- removes the elements in
14656
    the given range
14657
    @sa @ref erase(const typename object_t::key_type&) -- removes the element
14658
    from an object at the given key
14659
    @sa @ref erase(const size_type) -- removes the element from an array at
14660
    the given index
14661
14662
    @since version 1.0.0
14663
    */
14664
    template<class IteratorType, typename std::enable_if<
14665
                 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
14666
                 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
14667
             = 0>
14668
    IteratorType erase(IteratorType pos)
14669
0
    {
14670
0
        // make sure iterator fits the current value
14671
0
        if (JSON_UNLIKELY(this != pos.m_object))
14672
0
        {
14673
0
            JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
14674
0
        }
14675
0
14676
0
        IteratorType result = end();
14677
0
14678
0
        switch (m_type)
14679
0
        {
14680
0
            case value_t::boolean:
14681
0
            case value_t::number_float:
14682
0
            case value_t::number_integer:
14683
0
            case value_t::number_unsigned:
14684
0
            case value_t::string:
14685
0
            {
14686
0
                if (JSON_UNLIKELY(not pos.m_it.primitive_iterator.is_begin()))
14687
0
                {
14688
0
                    JSON_THROW(invalid_iterator::create(205, "iterator out of range"));
14689
0
                }
14690
0
14691
0
                if (is_string())
14692
0
                {
14693
0
                    AllocatorType<string_t> alloc;
14694
0
                    std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
14695
0
                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
14696
0
                    m_value.string = nullptr;
14697
0
                }
14698
0
14699
0
                m_type = value_t::null;
14700
0
                assert_invariant();
14701
0
                break;
14702
0
            }
14703
0
14704
0
            case value_t::object:
14705
0
            {
14706
0
                result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
14707
0
                break;
14708
0
            }
14709
0
14710
0
            case value_t::array:
14711
0
            {
14712
0
                result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
14713
0
                break;
14714
0
            }
14715
0
14716
0
            default:
14717
0
                JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
14718
0
        }
14719
0
14720
0
        return result;
14721
0
    }
14722
14723
    /*!
14724
    @brief remove elements given an iterator range
14725
14726
    Removes the element specified by the range `[first; last)`. The iterator
14727
    @a first does not need to be dereferenceable if `first == last`: erasing
14728
    an empty range is a no-op.
14729
14730
    If called on a primitive type other than `null`, the resulting JSON value
14731
    will be `null`.
14732
14733
    @param[in] first iterator to the beginning of the range to remove
14734
    @param[in] last iterator past the end of the range to remove
14735
    @return Iterator following the last removed element. If the iterator @a
14736
    second refers to the last element, the `end()` iterator is returned.
14737
14738
    @tparam IteratorType an @ref iterator or @ref const_iterator
14739
14740
    @post Invalidates iterators and references at or after the point of the
14741
    erase, including the `end()` iterator.
14742
14743
    @throw type_error.307 if called on a `null` value; example: `"cannot use
14744
    erase() with null"`
14745
    @throw invalid_iterator.203 if called on iterators which does not belong
14746
    to the current JSON value; example: `"iterators do not fit current value"`
14747
    @throw invalid_iterator.204 if called on a primitive type with invalid
14748
    iterators (i.e., if `first != begin()` and `last != end()`); example:
14749
    `"iterators out of range"`
14750
14751
    @complexity The complexity depends on the type:
14752
    - objects: `log(size()) + std::distance(first, last)`
14753
    - arrays: linear in the distance between @a first and @a last, plus linear
14754
      in the distance between @a last and end of the container
14755
    - strings: linear in the length of the string
14756
    - other types: constant
14757
14758
    @liveexample{The example shows the result of `erase()` for different JSON
14759
    types.,erase__IteratorType_IteratorType}
14760
14761
    @sa @ref erase(IteratorType) -- removes the element at a given position
14762
    @sa @ref erase(const typename object_t::key_type&) -- removes the element
14763
    from an object at the given key
14764
    @sa @ref erase(const size_type) -- removes the element from an array at
14765
    the given index
14766
14767
    @since version 1.0.0
14768
    */
14769
    template<class IteratorType, typename std::enable_if<
14770
                 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
14771
                 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
14772
             = 0>
14773
    IteratorType erase(IteratorType first, IteratorType last)
14774
    {
14775
        // make sure iterator fits the current value
14776
        if (JSON_UNLIKELY(this != first.m_object or this != last.m_object))
14777
        {
14778
            JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value"));
14779
        }
14780
14781
        IteratorType result = end();
14782
14783
        switch (m_type)
14784
        {
14785
            case value_t::boolean:
14786
            case value_t::number_float:
14787
            case value_t::number_integer:
14788
            case value_t::number_unsigned:
14789
            case value_t::string:
14790
            {
14791
                if (JSON_LIKELY(not first.m_it.primitive_iterator.is_begin()
14792
                                or not last.m_it.primitive_iterator.is_end()))
14793
                {
14794
                    JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
14795
                }
14796
14797
                if (is_string())
14798
                {
14799
                    AllocatorType<string_t> alloc;
14800
                    std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
14801
                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
14802
                    m_value.string = nullptr;
14803
                }
14804
14805
                m_type = value_t::null;
14806
                assert_invariant();
14807
                break;
14808
            }
14809
14810
            case value_t::object:
14811
            {
14812
                result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
14813
                                              last.m_it.object_iterator);
14814
                break;
14815
            }
14816
14817
            case value_t::array:
14818
            {
14819
                result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
14820
                                             last.m_it.array_iterator);
14821
                break;
14822
            }
14823
14824
            default:
14825
                JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
14826
        }
14827
14828
        return result;
14829
    }
14830
14831
    /*!
14832
    @brief remove element from a JSON object given a key
14833
14834
    Removes elements from a JSON object with the key value @a key.
14835
14836
    @param[in] key value of the elements to remove
14837
14838
    @return Number of elements removed. If @a ObjectType is the default
14839
    `std::map` type, the return value will always be `0` (@a key was not
14840
    found) or `1` (@a key was found).
14841
14842
    @post References and iterators to the erased elements are invalidated.
14843
    Other references and iterators are not affected.
14844
14845
    @throw type_error.307 when called on a type other than JSON object;
14846
    example: `"cannot use erase() with null"`
14847
14848
    @complexity `log(size()) + count(key)`
14849
14850
    @liveexample{The example shows the effect of `erase()`.,erase__key_type}
14851
14852
    @sa @ref erase(IteratorType) -- removes the element at a given position
14853
    @sa @ref erase(IteratorType, IteratorType) -- removes the elements in
14854
    the given range
14855
    @sa @ref erase(const size_type) -- removes the element from an array at
14856
    the given index
14857
14858
    @since version 1.0.0
14859
    */
14860
    size_type erase(const typename object_t::key_type& key)
14861
    {
14862
        // this erase only works for objects
14863
        if (JSON_LIKELY(is_object()))
14864
        {
14865
            return m_value.object->erase(key);
14866
        }
14867
14868
        JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
14869
    }
14870
14871
    /*!
14872
    @brief remove element from a JSON array given an index
14873
14874
    Removes element from a JSON array at the index @a idx.
14875
14876
    @param[in] idx index of the element to remove
14877
14878
    @throw type_error.307 when called on a type other than JSON object;
14879
    example: `"cannot use erase() with null"`
14880
    @throw out_of_range.401 when `idx >= size()`; example: `"array index 17
14881
    is out of range"`
14882
14883
    @complexity Linear in distance between @a idx and the end of the container.
14884
14885
    @liveexample{The example shows the effect of `erase()`.,erase__size_type}
14886
14887
    @sa @ref erase(IteratorType) -- removes the element at a given position
14888
    @sa @ref erase(IteratorType, IteratorType) -- removes the elements in
14889
    the given range
14890
    @sa @ref erase(const typename object_t::key_type&) -- removes the element
14891
    from an object at the given key
14892
14893
    @since version 1.0.0
14894
    */
14895
    void erase(const size_type idx)
14896
    {
14897
        // this erase only works for arrays
14898
        if (JSON_LIKELY(is_array()))
14899
        {
14900
            if (JSON_UNLIKELY(idx >= size()))
14901
            {
14902
                JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
14903
            }
14904
14905
            m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
14906
        }
14907
        else
14908
        {
14909
            JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
14910
        }
14911
    }
14912
14913
    /// @}
14914
14915
14916
    ////////////
14917
    // lookup //
14918
    ////////////
14919
14920
    /// @name lookup
14921
    /// @{
14922
14923
    /*!
14924
    @brief find an element in a JSON object
14925
14926
    Finds an element in a JSON object with key equivalent to @a key. If the
14927
    element is not found or the JSON value is not an object, end() is
14928
    returned.
14929
14930
    @note This method always returns @ref end() when executed on a JSON type
14931
          that is not an object.
14932
14933
    @param[in] key key value of the element to search for.
14934
14935
    @return Iterator to an element with key equivalent to @a key. If no such
14936
    element is found or the JSON value is not an object, past-the-end (see
14937
    @ref end()) iterator is returned.
14938
14939
    @complexity Logarithmic in the size of the JSON object.
14940
14941
    @liveexample{The example shows how `find()` is used.,find__key_type}
14942
14943
    @since version 1.0.0
14944
    */
14945
    template<typename KeyT>
14946
    iterator find(KeyT&& key)
14947
15
    {
14948
15
        auto result = end();
14949
15
14950
15
        if (is_object())
14951
14
        {
14952
14
            result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
14953
14
        }
14954
15
14955
15
        return result;
14956
15
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE4findIRA15_KcEENS_6detail9iter_implISA_EEOT_
Line
Count
Source
14947
2
    {
14948
2
        auto result = end();
14949
2
14950
2
        if (is_object())
14951
2
        {
14952
2
            result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
14953
2
        }
14954
2
14955
2
        return result;
14956
2
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE4findIRA9_KcEENS_6detail9iter_implISA_EEOT_
Line
Count
Source
14947
13
    {
14948
13
        auto result = end();
14949
13
14950
13
        if (is_object())
14951
12
        {
14952
12
            result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
14953
12
        }
14954
13
14955
13
        return result;
14956
13
    }
14957
14958
    /*!
14959
    @brief find an element in a JSON object
14960
    @copydoc find(KeyT&&)
14961
    */
14962
    template<typename KeyT>
14963
    const_iterator find(KeyT&& key) const
14964
    {
14965
        auto result = cend();
14966
14967
        if (is_object())
14968
        {
14969
            result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
14970
        }
14971
14972
        return result;
14973
    }
14974
14975
    /*!
14976
    @brief returns the number of occurrences of a key in a JSON object
14977
14978
    Returns the number of elements with key @a key. If ObjectType is the
14979
    default `std::map` type, the return value will always be `0` (@a key was
14980
    not found) or `1` (@a key was found).
14981
14982
    @note This method always returns `0` when executed on a JSON type that is
14983
          not an object.
14984
14985
    @param[in] key key value of the element to count
14986
14987
    @return Number of elements with key @a key. If the JSON value is not an
14988
    object, the return value will be `0`.
14989
14990
    @complexity Logarithmic in the size of the JSON object.
14991
14992
    @liveexample{The example shows how `count()` is used.,count}
14993
14994
    @since version 1.0.0
14995
    */
14996
    template<typename KeyT>
14997
    size_type count(KeyT&& key) const
14998
    {
14999
        // return 0 for all nonobject types
15000
        return is_object() ? m_value.object->count(std::forward<KeyT>(key)) : 0;
15001
    }
15002
15003
    /// @}
15004
15005
15006
    ///////////////
15007
    // iterators //
15008
    ///////////////
15009
15010
    /// @name iterators
15011
    /// @{
15012
15013
    /*!
15014
    @brief returns an iterator to the first element
15015
15016
    Returns an iterator to the first element.
15017
15018
    @image html range-begin-end.svg "Illustration from cppreference.com"
15019
15020
    @return iterator to the first element
15021
15022
    @complexity Constant.
15023
15024
    @requirement This function helps `basic_json` satisfying the
15025
    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
15026
    requirements:
15027
    - The complexity is constant.
15028
15029
    @liveexample{The following code shows an example for `begin()`.,begin}
15030
15031
    @sa @ref cbegin() -- returns a const iterator to the beginning
15032
    @sa @ref end() -- returns an iterator to the end
15033
    @sa @ref cend() -- returns a const iterator to the end
15034
15035
    @since version 1.0.0
15036
    */
15037
    iterator begin() noexcept
15038
590
    {
15039
590
        iterator result(this);
15040
590
        result.set_begin();
15041
590
        return result;
15042
590
    }
15043
15044
    /*!
15045
    @copydoc basic_json::cbegin()
15046
    */
15047
    const_iterator begin() const noexcept
15048
    {
15049
        return cbegin();
15050
    }
15051
15052
    /*!
15053
    @brief returns a const iterator to the first element
15054
15055
    Returns a const iterator to the first element.
15056
15057
    @image html range-begin-end.svg "Illustration from cppreference.com"
15058
15059
    @return const iterator to the first element
15060
15061
    @complexity Constant.
15062
15063
    @requirement This function helps `basic_json` satisfying the
15064
    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
15065
    requirements:
15066
    - The complexity is constant.
15067
    - Has the semantics of `const_cast<const basic_json&>(*this).begin()`.
15068
15069
    @liveexample{The following code shows an example for `cbegin()`.,cbegin}
15070
15071
    @sa @ref begin() -- returns an iterator to the beginning
15072
    @sa @ref end() -- returns an iterator to the end
15073
    @sa @ref cend() -- returns a const iterator to the end
15074
15075
    @since version 1.0.0
15076
    */
15077
    const_iterator cbegin() const noexcept
15078
    {
15079
        const_iterator result(this);
15080
        result.set_begin();
15081
        return result;
15082
    }
15083
15084
    /*!
15085
    @brief returns an iterator to one past the last element
15086
15087
    Returns an iterator to one past the last element.
15088
15089
    @image html range-begin-end.svg "Illustration from cppreference.com"
15090
15091
    @return iterator one past the last element
15092
15093
    @complexity Constant.
15094
15095
    @requirement This function helps `basic_json` satisfying the
15096
    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
15097
    requirements:
15098
    - The complexity is constant.
15099
15100
    @liveexample{The following code shows an example for `end()`.,end}
15101
15102
    @sa @ref cend() -- returns a const iterator to the end
15103
    @sa @ref begin() -- returns an iterator to the beginning
15104
    @sa @ref cbegin() -- returns a const iterator to the beginning
15105
15106
    @since version 1.0.0
15107
    */
15108
    iterator end() noexcept
15109
1.98k
    {
15110
1.98k
        iterator result(this);
15111
1.98k
        result.set_end();
15112
1.98k
        return result;
15113
1.98k
    }
15114
15115
    /*!
15116
    @copydoc basic_json::cend()
15117
    */
15118
    const_iterator end() const noexcept
15119
    {
15120
        return cend();
15121
    }
15122
15123
    /*!
15124
    @brief returns a const iterator to one past the last element
15125
15126
    Returns a const iterator to one past the last element.
15127
15128
    @image html range-begin-end.svg "Illustration from cppreference.com"
15129
15130
    @return const iterator one past the last element
15131
15132
    @complexity Constant.
15133
15134
    @requirement This function helps `basic_json` satisfying the
15135
    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
15136
    requirements:
15137
    - The complexity is constant.
15138
    - Has the semantics of `const_cast<const basic_json&>(*this).end()`.
15139
15140
    @liveexample{The following code shows an example for `cend()`.,cend}
15141
15142
    @sa @ref end() -- returns an iterator to the end
15143
    @sa @ref begin() -- returns an iterator to the beginning
15144
    @sa @ref cbegin() -- returns a const iterator to the beginning
15145
15146
    @since version 1.0.0
15147
    */
15148
    const_iterator cend() const noexcept
15149
    {
15150
        const_iterator result(this);
15151
        result.set_end();
15152
        return result;
15153
    }
15154
15155
    /*!
15156
    @brief returns an iterator to the reverse-beginning
15157
15158
    Returns an iterator to the reverse-beginning; that is, the last element.
15159
15160
    @image html range-rbegin-rend.svg "Illustration from cppreference.com"
15161
15162
    @complexity Constant.
15163
15164
    @requirement This function helps `basic_json` satisfying the
15165
    [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
15166
    requirements:
15167
    - The complexity is constant.
15168
    - Has the semantics of `reverse_iterator(end())`.
15169
15170
    @liveexample{The following code shows an example for `rbegin()`.,rbegin}
15171
15172
    @sa @ref crbegin() -- returns a const reverse iterator to the beginning
15173
    @sa @ref rend() -- returns a reverse iterator to the end
15174
    @sa @ref crend() -- returns a const reverse iterator to the end
15175
15176
    @since version 1.0.0
15177
    */
15178
    reverse_iterator rbegin() noexcept
15179
    {
15180
        return reverse_iterator(end());
15181
    }
15182
15183
    /*!
15184
    @copydoc basic_json::crbegin()
15185
    */
15186
    const_reverse_iterator rbegin() const noexcept
15187
    {
15188
        return crbegin();
15189
    }
15190
15191
    /*!
15192
    @brief returns an iterator to the reverse-end
15193
15194
    Returns an iterator to the reverse-end; that is, one before the first
15195
    element.
15196
15197
    @image html range-rbegin-rend.svg "Illustration from cppreference.com"
15198
15199
    @complexity Constant.
15200
15201
    @requirement This function helps `basic_json` satisfying the
15202
    [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
15203
    requirements:
15204
    - The complexity is constant.
15205
    - Has the semantics of `reverse_iterator(begin())`.
15206
15207
    @liveexample{The following code shows an example for `rend()`.,rend}
15208
15209
    @sa @ref crend() -- returns a const reverse iterator to the end
15210
    @sa @ref rbegin() -- returns a reverse iterator to the beginning
15211
    @sa @ref crbegin() -- returns a const reverse iterator to the beginning
15212
15213
    @since version 1.0.0
15214
    */
15215
    reverse_iterator rend() noexcept
15216
    {
15217
        return reverse_iterator(begin());
15218
    }
15219
15220
    /*!
15221
    @copydoc basic_json::crend()
15222
    */
15223
    const_reverse_iterator rend() const noexcept
15224
    {
15225
        return crend();
15226
    }
15227
15228
    /*!
15229
    @brief returns a const reverse iterator to the last element
15230
15231
    Returns a const iterator to the reverse-beginning; that is, the last
15232
    element.
15233
15234
    @image html range-rbegin-rend.svg "Illustration from cppreference.com"
15235
15236
    @complexity Constant.
15237
15238
    @requirement This function helps `basic_json` satisfying the
15239
    [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
15240
    requirements:
15241
    - The complexity is constant.
15242
    - Has the semantics of `const_cast<const basic_json&>(*this).rbegin()`.
15243
15244
    @liveexample{The following code shows an example for `crbegin()`.,crbegin}
15245
15246
    @sa @ref rbegin() -- returns a reverse iterator to the beginning
15247
    @sa @ref rend() -- returns a reverse iterator to the end
15248
    @sa @ref crend() -- returns a const reverse iterator to the end
15249
15250
    @since version 1.0.0
15251
    */
15252
    const_reverse_iterator crbegin() const noexcept
15253
    {
15254
        return const_reverse_iterator(cend());
15255
    }
15256
15257
    /*!
15258
    @brief returns a const reverse iterator to one before the first
15259
15260
    Returns a const reverse iterator to the reverse-end; that is, one before
15261
    the first element.
15262
15263
    @image html range-rbegin-rend.svg "Illustration from cppreference.com"
15264
15265
    @complexity Constant.
15266
15267
    @requirement This function helps `basic_json` satisfying the
15268
    [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
15269
    requirements:
15270
    - The complexity is constant.
15271
    - Has the semantics of `const_cast<const basic_json&>(*this).rend()`.
15272
15273
    @liveexample{The following code shows an example for `crend()`.,crend}
15274
15275
    @sa @ref rend() -- returns a reverse iterator to the end
15276
    @sa @ref rbegin() -- returns a reverse iterator to the beginning
15277
    @sa @ref crbegin() -- returns a const reverse iterator to the beginning
15278
15279
    @since version 1.0.0
15280
    */
15281
    const_reverse_iterator crend() const noexcept
15282
    {
15283
        return const_reverse_iterator(cbegin());
15284
    }
15285
15286
  public:
15287
    /*!
15288
    @brief wrapper to access iterator member functions in range-based for
15289
15290
    This function allows to access @ref iterator::key() and @ref
15291
    iterator::value() during range-based for loops. In these loops, a
15292
    reference to the JSON values is returned, so there is no access to the
15293
    underlying iterator.
15294
15295
    For loop without iterator_wrapper:
15296
15297
    @code{cpp}
15298
    for (auto it = j_object.begin(); it != j_object.end(); ++it)
15299
    {
15300
        std::cout << "key: " << it.key() << ", value:" << it.value() << '\n';
15301
    }
15302
    @endcode
15303
15304
    Range-based for loop without iterator proxy:
15305
15306
    @code{cpp}
15307
    for (auto it : j_object)
15308
    {
15309
        // "it" is of type json::reference and has no key() member
15310
        std::cout << "value: " << it << '\n';
15311
    }
15312
    @endcode
15313
15314
    Range-based for loop with iterator proxy:
15315
15316
    @code{cpp}
15317
    for (auto it : json::iterator_wrapper(j_object))
15318
    {
15319
        std::cout << "key: " << it.key() << ", value:" << it.value() << '\n';
15320
    }
15321
    @endcode
15322
15323
    @note When iterating over an array, `key()` will return the index of the
15324
          element as string (see example).
15325
15326
    @param[in] ref  reference to a JSON value
15327
    @return iteration proxy object wrapping @a ref with an interface to use in
15328
            range-based for loops
15329
15330
    @liveexample{The following code shows how the wrapper is used,iterator_wrapper}
15331
15332
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
15333
    changes in the JSON value.
15334
15335
    @complexity Constant.
15336
15337
    @note The name of this function is not yet final and may change in the
15338
    future.
15339
15340
    @deprecated This stream operator is deprecated and will be removed in
15341
                future 4.0.0 of the library. Please use @ref items() instead;
15342
                that is, replace `json::iterator_wrapper(j)` with `j.items()`.
15343
    */
15344
    JSON_DEPRECATED
15345
    static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
15346
    {
15347
        return ref.items();
15348
    }
15349
15350
    /*!
15351
    @copydoc iterator_wrapper(reference)
15352
    */
15353
    JSON_DEPRECATED
15354
    static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
15355
    {
15356
        return ref.items();
15357
    }
15358
15359
    /*!
15360
    @brief helper to access iterator member functions in range-based for
15361
15362
    This function allows to access @ref iterator::key() and @ref
15363
    iterator::value() during range-based for loops. In these loops, a
15364
    reference to the JSON values is returned, so there is no access to the
15365
    underlying iterator.
15366
15367
    For loop without `items()` function:
15368
15369
    @code{cpp}
15370
    for (auto it = j_object.begin(); it != j_object.end(); ++it)
15371
    {
15372
        std::cout << "key: " << it.key() << ", value:" << it.value() << '\n';
15373
    }
15374
    @endcode
15375
15376
    Range-based for loop without `items()` function:
15377
15378
    @code{cpp}
15379
    for (auto it : j_object)
15380
    {
15381
        // "it" is of type json::reference and has no key() member
15382
        std::cout << "value: " << it << '\n';
15383
    }
15384
    @endcode
15385
15386
    Range-based for loop with `items()` function:
15387
15388
    @code{cpp}
15389
    for (auto it : j_object.items())
15390
    {
15391
        std::cout << "key: " << it.key() << ", value:" << it.value() << '\n';
15392
    }
15393
    @endcode
15394
15395
    @note When iterating over an array, `key()` will return the index of the
15396
          element as string (see example). For primitive types (e.g., numbers),
15397
          `key()` returns an empty string.
15398
15399
    @return iteration proxy object wrapping @a ref with an interface to use in
15400
            range-based for loops
15401
15402
    @liveexample{The following code shows how the function is used.,items}
15403
15404
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
15405
    changes in the JSON value.
15406
15407
    @complexity Constant.
15408
15409
    @since version 3.1.0.
15410
    */
15411
    iteration_proxy<iterator> items() noexcept
15412
    {
15413
        return iteration_proxy<iterator>(*this);
15414
    }
15415
15416
    /*!
15417
    @copydoc items()
15418
    */
15419
    iteration_proxy<const_iterator> items() const noexcept
15420
    {
15421
        return iteration_proxy<const_iterator>(*this);
15422
    }
15423
15424
    /// @}
15425
15426
15427
    //////////////
15428
    // capacity //
15429
    //////////////
15430
15431
    /// @name capacity
15432
    /// @{
15433
15434
    /*!
15435
    @brief checks whether the container is empty.
15436
15437
    Checks if a JSON value has no elements (i.e. whether its @ref size is `0`).
15438
15439
    @return The return value depends on the different types and is
15440
            defined as follows:
15441
            Value type  | return value
15442
            ----------- | -------------
15443
            null        | `true`
15444
            boolean     | `false`
15445
            string      | `false`
15446
            number      | `false`
15447
            object      | result of function `object_t::empty()`
15448
            array       | result of function `array_t::empty()`
15449
15450
    @liveexample{The following code uses `empty()` to check if a JSON
15451
    object contains any elements.,empty}
15452
15453
    @complexity Constant, as long as @ref array_t and @ref object_t satisfy
15454
    the Container concept; that is, their `empty()` functions have constant
15455
    complexity.
15456
15457
    @iterators No changes.
15458
15459
    @exceptionsafety No-throw guarantee: this function never throws exceptions.
15460
15461
    @note This function does not return whether a string stored as JSON value
15462
    is empty - it returns whether the JSON container itself is empty which is
15463
    false in the case of a string.
15464
15465
    @requirement This function helps `basic_json` satisfying the
15466
    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
15467
    requirements:
15468
    - The complexity is constant.
15469
    - Has the semantics of `begin() == end()`.
15470
15471
    @sa @ref size() -- returns the number of elements
15472
15473
    @since version 1.0.0
15474
    */
15475
    bool empty() const noexcept
15476
    {
15477
        switch (m_type)
15478
        {
15479
            case value_t::null:
15480
            {
15481
                // null values are empty
15482
                return true;
15483
            }
15484
15485
            case value_t::array:
15486
            {
15487
                // delegate call to array_t::empty()
15488
                return m_value.array->empty();
15489
            }
15490
15491
            case value_t::object:
15492
            {
15493
                // delegate call to object_t::empty()
15494
                return m_value.object->empty();
15495
            }
15496
15497
            default:
15498
            {
15499
                // all other types are nonempty
15500
                return false;
15501
            }
15502
        }
15503
    }
15504
15505
    /*!
15506
    @brief returns the number of elements
15507
15508
    Returns the number of elements in a JSON value.
15509
15510
    @return The return value depends on the different types and is
15511
            defined as follows:
15512
            Value type  | return value
15513
            ----------- | -------------
15514
            null        | `0`
15515
            boolean     | `1`
15516
            string      | `1`
15517
            number      | `1`
15518
            object      | result of function object_t::size()
15519
            array       | result of function array_t::size()
15520
15521
    @liveexample{The following code calls `size()` on the different value
15522
    types.,size}
15523
15524
    @complexity Constant, as long as @ref array_t and @ref object_t satisfy
15525
    the Container concept; that is, their size() functions have constant
15526
    complexity.
15527
15528
    @iterators No changes.
15529
15530
    @exceptionsafety No-throw guarantee: this function never throws exceptions.
15531
15532
    @note This function does not return the length of a string stored as JSON
15533
    value - it returns the number of elements in the JSON value which is 1 in
15534
    the case of a string.
15535
15536
    @requirement This function helps `basic_json` satisfying the
15537
    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
15538
    requirements:
15539
    - The complexity is constant.
15540
    - Has the semantics of `std::distance(begin(), end())`.
15541
15542
    @sa @ref empty() -- checks whether the container is empty
15543
    @sa @ref max_size() -- returns the maximal number of elements
15544
15545
    @since version 1.0.0
15546
    */
15547
    size_type size() const noexcept
15548
33
    {
15549
33
        switch (m_type)
15550
33
        {
15551
33
            case value_t::null:
15552
13
            {
15553
13
                // null values are empty
15554
13
                return 0;
15555
33
            }
15556
33
15557
33
            case value_t::array:
15558
20
            {
15559
20
                // delegate call to array_t::size()
15560
20
                return m_value.array->size();
15561
33
            }
15562
33
15563
33
            case value_t::object:
15564
0
            {
15565
0
                // delegate call to object_t::size()
15566
0
                return m_value.object->size();
15567
33
            }
15568
33
15569
33
            default:
15570
0
            {
15571
0
                // all other types have size 1
15572
0
                return 1;
15573
0
            }
15574
0
        }
15575
0
    }
15576
15577
    /*!
15578
    @brief returns the maximum possible number of elements
15579
15580
    Returns the maximum number of elements a JSON value is able to hold due to
15581
    system or library implementation limitations, i.e. `std::distance(begin(),
15582
    end())` for the JSON value.
15583
15584
    @return The return value depends on the different types and is
15585
            defined as follows:
15586
            Value type  | return value
15587
            ----------- | -------------
15588
            null        | `0` (same as `size()`)
15589
            boolean     | `1` (same as `size()`)
15590
            string      | `1` (same as `size()`)
15591
            number      | `1` (same as `size()`)
15592
            object      | result of function `object_t::max_size()`
15593
            array       | result of function `array_t::max_size()`
15594
15595
    @liveexample{The following code calls `max_size()` on the different value
15596
    types. Note the output is implementation specific.,max_size}
15597
15598
    @complexity Constant, as long as @ref array_t and @ref object_t satisfy
15599
    the Container concept; that is, their `max_size()` functions have constant
15600
    complexity.
15601
15602
    @iterators No changes.
15603
15604
    @exceptionsafety No-throw guarantee: this function never throws exceptions.
15605
15606
    @requirement This function helps `basic_json` satisfying the
15607
    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
15608
    requirements:
15609
    - The complexity is constant.
15610
    - Has the semantics of returning `b.size()` where `b` is the largest
15611
      possible JSON value.
15612
15613
    @sa @ref size() -- returns the number of elements
15614
15615
    @since version 1.0.0
15616
    */
15617
    size_type max_size() const noexcept
15618
0
    {
15619
0
        switch (m_type)
15620
0
        {
15621
0
            case value_t::array:
15622
0
            {
15623
0
                // delegate call to array_t::max_size()
15624
0
                return m_value.array->max_size();
15625
0
            }
15626
0
15627
0
            case value_t::object:
15628
0
            {
15629
0
                // delegate call to object_t::max_size()
15630
0
                return m_value.object->max_size();
15631
0
            }
15632
0
15633
0
            default:
15634
0
            {
15635
0
                // all other types have max_size() == size()
15636
0
                return size();
15637
0
            }
15638
0
        }
15639
0
    }
15640
15641
    /// @}
15642
15643
15644
    ///////////////
15645
    // modifiers //
15646
    ///////////////
15647
15648
    /// @name modifiers
15649
    /// @{
15650
15651
    /*!
15652
    @brief clears the contents
15653
15654
    Clears the content of a JSON value and resets it to the default value as
15655
    if @ref basic_json(value_t) would have been called with the current value
15656
    type from @ref type():
15657
15658
    Value type  | initial value
15659
    ----------- | -------------
15660
    null        | `null`
15661
    boolean     | `false`
15662
    string      | `""`
15663
    number      | `0`
15664
    object      | `{}`
15665
    array       | `[]`
15666
15667
    @post Has the same effect as calling
15668
    @code {.cpp}
15669
    *this = basic_json(type());
15670
    @endcode
15671
15672
    @liveexample{The example below shows the effect of `clear()` to different
15673
    JSON types.,clear}
15674
15675
    @complexity Linear in the size of the JSON value.
15676
15677
    @iterators All iterators, pointers and references related to this container
15678
               are invalidated.
15679
15680
    @exceptionsafety No-throw guarantee: this function never throws exceptions.
15681
15682
    @sa @ref basic_json(value_t) -- constructor that creates an object with the
15683
        same value than calling `clear()`
15684
15685
    @since version 1.0.0
15686
    */
15687
    void clear() noexcept
15688
    {
15689
        switch (m_type)
15690
        {
15691
            case value_t::number_integer:
15692
            {
15693
                m_value.number_integer = 0;
15694
                break;
15695
            }
15696
15697
            case value_t::number_unsigned:
15698
            {
15699
                m_value.number_unsigned = 0;
15700
                break;
15701
            }
15702
15703
            case value_t::number_float:
15704
            {
15705
                m_value.number_float = 0.0;
15706
                break;
15707
            }
15708
15709
            case value_t::boolean:
15710
            {
15711
                m_value.boolean = false;
15712
                break;
15713
            }
15714
15715
            case value_t::string:
15716
            {
15717
                m_value.string->clear();
15718
                break;
15719
            }
15720
15721
            case value_t::array:
15722
            {
15723
                m_value.array->clear();
15724
                break;
15725
            }
15726
15727
            case value_t::object:
15728
            {
15729
                m_value.object->clear();
15730
                break;
15731
            }
15732
15733
            default:
15734
                break;
15735
        }
15736
    }
15737
15738
    /*!
15739
    @brief add an object to an array
15740
15741
    Appends the given element @a val to the end of the JSON value. If the
15742
    function is called on a JSON null value, an empty array is created before
15743
    appending @a val.
15744
15745
    @param[in] val the value to add to the JSON array
15746
15747
    @throw type_error.308 when called on a type other than JSON array or
15748
    null; example: `"cannot use push_back() with number"`
15749
15750
    @complexity Amortized constant.
15751
15752
    @liveexample{The example shows how `push_back()` and `+=` can be used to
15753
    add elements to a JSON array. Note how the `null` value was silently
15754
    converted to a JSON array.,push_back}
15755
15756
    @since version 1.0.0
15757
    */
15758
    void push_back(basic_json&& val)
15759
    {
15760
        // push_back only works for null objects or arrays
15761
        if (JSON_UNLIKELY(not(is_null() or is_array())))
15762
        {
15763
            JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
15764
        }
15765
15766
        // transform null object into an array
15767
        if (is_null())
15768
        {
15769
            m_type = value_t::array;
15770
            m_value = value_t::array;
15771
            assert_invariant();
15772
        }
15773
15774
        // add element to array (move semantics)
15775
        m_value.array->push_back(std::move(val));
15776
        // invalidate object
15777
        val.m_type = value_t::null;
15778
    }
15779
15780
    /*!
15781
    @brief add an object to an array
15782
    @copydoc push_back(basic_json&&)
15783
    */
15784
    reference operator+=(basic_json&& val)
15785
    {
15786
        push_back(std::move(val));
15787
        return *this;
15788
    }
15789
15790
    /*!
15791
    @brief add an object to an array
15792
    @copydoc push_back(basic_json&&)
15793
    */
15794
    void push_back(const basic_json& val)
15795
    {
15796
        // push_back only works for null objects or arrays
15797
        if (JSON_UNLIKELY(not(is_null() or is_array())))
15798
        {
15799
            JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
15800
        }
15801
15802
        // transform null object into an array
15803
        if (is_null())
15804
        {
15805
            m_type = value_t::array;
15806
            m_value = value_t::array;
15807
            assert_invariant();
15808
        }
15809
15810
        // add element to array
15811
        m_value.array->push_back(val);
15812
    }
15813
15814
    /*!
15815
    @brief add an object to an array
15816
    @copydoc push_back(basic_json&&)
15817
    */
15818
    reference operator+=(const basic_json& val)
15819
    {
15820
        push_back(val);
15821
        return *this;
15822
    }
15823
15824
    /*!
15825
    @brief add an object to an object
15826
15827
    Inserts the given element @a val to the JSON object. If the function is
15828
    called on a JSON null value, an empty object is created before inserting
15829
    @a val.
15830
15831
    @param[in] val the value to add to the JSON object
15832
15833
    @throw type_error.308 when called on a type other than JSON object or
15834
    null; example: `"cannot use push_back() with number"`
15835
15836
    @complexity Logarithmic in the size of the container, O(log(`size()`)).
15837
15838
    @liveexample{The example shows how `push_back()` and `+=` can be used to
15839
    add elements to a JSON object. Note how the `null` value was silently
15840
    converted to a JSON object.,push_back__object_t__value}
15841
15842
    @since version 1.0.0
15843
    */
15844
    void push_back(const typename object_t::value_type& val)
15845
    {
15846
        // push_back only works for null objects or objects
15847
        if (JSON_UNLIKELY(not(is_null() or is_object())))
15848
        {
15849
            JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
15850
        }
15851
15852
        // transform null object into an object
15853
        if (is_null())
15854
        {
15855
            m_type = value_t::object;
15856
            m_value = value_t::object;
15857
            assert_invariant();
15858
        }
15859
15860
        // add element to array
15861
        m_value.object->insert(val);
15862
    }
15863
15864
    /*!
15865
    @brief add an object to an object
15866
    @copydoc push_back(const typename object_t::value_type&)
15867
    */
15868
    reference operator+=(const typename object_t::value_type& val)
15869
    {
15870
        push_back(val);
15871
        return *this;
15872
    }
15873
15874
    /*!
15875
    @brief add an object to an object
15876
15877
    This function allows to use `push_back` with an initializer list. In case
15878
15879
    1. the current value is an object,
15880
    2. the initializer list @a init contains only two elements, and
15881
    3. the first element of @a init is a string,
15882
15883
    @a init is converted into an object element and added using
15884
    @ref push_back(const typename object_t::value_type&). Otherwise, @a init
15885
    is converted to a JSON value and added using @ref push_back(basic_json&&).
15886
15887
    @param[in] init  an initializer list
15888
15889
    @complexity Linear in the size of the initializer list @a init.
15890
15891
    @note This function is required to resolve an ambiguous overload error,
15892
          because pairs like `{"key", "value"}` can be both interpreted as
15893
          `object_t::value_type` or `std::initializer_list<basic_json>`, see
15894
          https://github.com/nlohmann/json/issues/235 for more information.
15895
15896
    @liveexample{The example shows how initializer lists are treated as
15897
    objects when possible.,push_back__initializer_list}
15898
    */
15899
    void push_back(initializer_list_t init)
15900
    {
15901
        if (is_object() and init.size() == 2 and (*init.begin())->is_string())
15902
        {
15903
            basic_json&& key = init.begin()->moved_or_copied();
15904
            push_back(typename object_t::value_type(
15905
                          std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
15906
        }
15907
        else
15908
        {
15909
            push_back(basic_json(init));
15910
        }
15911
    }
15912
15913
    /*!
15914
    @brief add an object to an object
15915
    @copydoc push_back(initializer_list_t)
15916
    */
15917
    reference operator+=(initializer_list_t init)
15918
    {
15919
        push_back(init);
15920
        return *this;
15921
    }
15922
15923
    /*!
15924
    @brief add an object to an array
15925
15926
    Creates a JSON value from the passed parameters @a args to the end of the
15927
    JSON value. If the function is called on a JSON null value, an empty array
15928
    is created before appending the value created from @a args.
15929
15930
    @param[in] args arguments to forward to a constructor of @ref basic_json
15931
    @tparam Args compatible types to create a @ref basic_json object
15932
15933
    @throw type_error.311 when called on a type other than JSON array or
15934
    null; example: `"cannot use emplace_back() with number"`
15935
15936
    @complexity Amortized constant.
15937
15938
    @liveexample{The example shows how `push_back()` can be used to add
15939
    elements to a JSON array. Note how the `null` value was silently converted
15940
    to a JSON array.,emplace_back}
15941
15942
    @since version 2.0.8
15943
    */
15944
    template<class... Args>
15945
    void emplace_back(Args&& ... args)
15946
    {
15947
        // emplace_back only works for null objects or arrays
15948
        if (JSON_UNLIKELY(not(is_null() or is_array())))
15949
        {
15950
            JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name())));
15951
        }
15952
15953
        // transform null object into an array
15954
        if (is_null())
15955
        {
15956
            m_type = value_t::array;
15957
            m_value = value_t::array;
15958
            assert_invariant();
15959
        }
15960
15961
        // add element to array (perfect forwarding)
15962
        m_value.array->emplace_back(std::forward<Args>(args)...);
15963
    }
15964
15965
    /*!
15966
    @brief add an object to an object if key does not exist
15967
15968
    Inserts a new element into a JSON object constructed in-place with the
15969
    given @a args if there is no element with the key in the container. If the
15970
    function is called on a JSON null value, an empty object is created before
15971
    appending the value created from @a args.
15972
15973
    @param[in] args arguments to forward to a constructor of @ref basic_json
15974
    @tparam Args compatible types to create a @ref basic_json object
15975
15976
    @return a pair consisting of an iterator to the inserted element, or the
15977
            already-existing element if no insertion happened, and a bool
15978
            denoting whether the insertion took place.
15979
15980
    @throw type_error.311 when called on a type other than JSON object or
15981
    null; example: `"cannot use emplace() with number"`
15982
15983
    @complexity Logarithmic in the size of the container, O(log(`size()`)).
15984
15985
    @liveexample{The example shows how `emplace()` can be used to add elements
15986
    to a JSON object. Note how the `null` value was silently converted to a
15987
    JSON object. Further note how no value is added if there was already one
15988
    value stored with the same key.,emplace}
15989
15990
    @since version 2.0.8
15991
    */
15992
    template<class... Args>
15993
    std::pair<iterator, bool> emplace(Args&& ... args)
15994
    {
15995
        // emplace only works for null objects or arrays
15996
        if (JSON_UNLIKELY(not(is_null() or is_object())))
15997
        {
15998
            JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name())));
15999
        }
16000
16001
        // transform null object into an object
16002
        if (is_null())
16003
        {
16004
            m_type = value_t::object;
16005
            m_value = value_t::object;
16006
            assert_invariant();
16007
        }
16008
16009
        // add element to array (perfect forwarding)
16010
        auto res = m_value.object->emplace(std::forward<Args>(args)...);
16011
        // create result iterator and set iterator to the result of emplace
16012
        auto it = begin();
16013
        it.m_it.object_iterator = res.first;
16014
16015
        // return pair of iterator and boolean
16016
        return {it, res.second};
16017
    }
16018
16019
    /*!
16020
    @brief inserts element
16021
16022
    Inserts element @a val before iterator @a pos.
16023
16024
    @param[in] pos iterator before which the content will be inserted; may be
16025
    the end() iterator
16026
    @param[in] val element to insert
16027
    @return iterator pointing to the inserted @a val.
16028
16029
    @throw type_error.309 if called on JSON values other than arrays;
16030
    example: `"cannot use insert() with string"`
16031
    @throw invalid_iterator.202 if @a pos is not an iterator of *this;
16032
    example: `"iterator does not fit current value"`
16033
16034
    @complexity Constant plus linear in the distance between @a pos and end of
16035
    the container.
16036
16037
    @liveexample{The example shows how `insert()` is used.,insert}
16038
16039
    @since version 1.0.0
16040
    */
16041
    iterator insert(const_iterator pos, const basic_json& val)
16042
    {
16043
        // insert only works for arrays
16044
        if (JSON_LIKELY(is_array()))
16045
        {
16046
            // check if iterator pos fits to this JSON value
16047
            if (JSON_UNLIKELY(pos.m_object != this))
16048
            {
16049
                JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
16050
            }
16051
16052
            // insert to array and return iterator
16053
            iterator result(this);
16054
            result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
16055
            return result;
16056
        }
16057
16058
        JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
16059
    }
16060
16061
    /*!
16062
    @brief inserts element
16063
    @copydoc insert(const_iterator, const basic_json&)
16064
    */
16065
    iterator insert(const_iterator pos, basic_json&& val)
16066
    {
16067
        return insert(pos, val);
16068
    }
16069
16070
    /*!
16071
    @brief inserts elements
16072
16073
    Inserts @a cnt copies of @a val before iterator @a pos.
16074
16075
    @param[in] pos iterator before which the content will be inserted; may be
16076
    the end() iterator
16077
    @param[in] cnt number of copies of @a val to insert
16078
    @param[in] val element to insert
16079
    @return iterator pointing to the first element inserted, or @a pos if
16080
    `cnt==0`
16081
16082
    @throw type_error.309 if called on JSON values other than arrays; example:
16083
    `"cannot use insert() with string"`
16084
    @throw invalid_iterator.202 if @a pos is not an iterator of *this;
16085
    example: `"iterator does not fit current value"`
16086
16087
    @complexity Linear in @a cnt plus linear in the distance between @a pos
16088
    and end of the container.
16089
16090
    @liveexample{The example shows how `insert()` is used.,insert__count}
16091
16092
    @since version 1.0.0
16093
    */
16094
    iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
16095
    {
16096
        // insert only works for arrays
16097
        if (JSON_LIKELY(is_array()))
16098
        {
16099
            // check if iterator pos fits to this JSON value
16100
            if (JSON_UNLIKELY(pos.m_object != this))
16101
            {
16102
                JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
16103
            }
16104
16105
            // insert to array and return iterator
16106
            iterator result(this);
16107
            result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
16108
            return result;
16109
        }
16110
16111
        JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
16112
    }
16113
16114
    /*!
16115
    @brief inserts elements
16116
16117
    Inserts elements from range `[first, last)` before iterator @a pos.
16118
16119
    @param[in] pos iterator before which the content will be inserted; may be
16120
    the end() iterator
16121
    @param[in] first begin of the range of elements to insert
16122
    @param[in] last end of the range of elements to insert
16123
16124
    @throw type_error.309 if called on JSON values other than arrays; example:
16125
    `"cannot use insert() with string"`
16126
    @throw invalid_iterator.202 if @a pos is not an iterator of *this;
16127
    example: `"iterator does not fit current value"`
16128
    @throw invalid_iterator.210 if @a first and @a last do not belong to the
16129
    same JSON value; example: `"iterators do not fit"`
16130
    @throw invalid_iterator.211 if @a first or @a last are iterators into
16131
    container for which insert is called; example: `"passed iterators may not
16132
    belong to container"`
16133
16134
    @return iterator pointing to the first element inserted, or @a pos if
16135
    `first==last`
16136
16137
    @complexity Linear in `std::distance(first, last)` plus linear in the
16138
    distance between @a pos and end of the container.
16139
16140
    @liveexample{The example shows how `insert()` is used.,insert__range}
16141
16142
    @since version 1.0.0
16143
    */
16144
    iterator insert(const_iterator pos, const_iterator first, const_iterator last)
16145
    {
16146
        // insert only works for arrays
16147
        if (JSON_UNLIKELY(not is_array()))
16148
        {
16149
            JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
16150
        }
16151
16152
        // check if iterator pos fits to this JSON value
16153
        if (JSON_UNLIKELY(pos.m_object != this))
16154
        {
16155
            JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
16156
        }
16157
16158
        // check if range iterators belong to the same JSON object
16159
        if (JSON_UNLIKELY(first.m_object != last.m_object))
16160
        {
16161
            JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
16162
        }
16163
16164
        if (JSON_UNLIKELY(first.m_object == this))
16165
        {
16166
            JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container"));
16167
        }
16168
16169
        // insert to array and return iterator
16170
        iterator result(this);
16171
        result.m_it.array_iterator = m_value.array->insert(
16172
                                         pos.m_it.array_iterator,
16173
                                         first.m_it.array_iterator,
16174
                                         last.m_it.array_iterator);
16175
        return result;
16176
    }
16177
16178
    /*!
16179
    @brief inserts elements
16180
16181
    Inserts elements from initializer list @a ilist before iterator @a pos.
16182
16183
    @param[in] pos iterator before which the content will be inserted; may be
16184
    the end() iterator
16185
    @param[in] ilist initializer list to insert the values from
16186
16187
    @throw type_error.309 if called on JSON values other than arrays; example:
16188
    `"cannot use insert() with string"`
16189
    @throw invalid_iterator.202 if @a pos is not an iterator of *this;
16190
    example: `"iterator does not fit current value"`
16191
16192
    @return iterator pointing to the first element inserted, or @a pos if
16193
    `ilist` is empty
16194
16195
    @complexity Linear in `ilist.size()` plus linear in the distance between
16196
    @a pos and end of the container.
16197
16198
    @liveexample{The example shows how `insert()` is used.,insert__ilist}
16199
16200
    @since version 1.0.0
16201
    */
16202
    iterator insert(const_iterator pos, initializer_list_t ilist)
16203
    {
16204
        // insert only works for arrays
16205
        if (JSON_UNLIKELY(not is_array()))
16206
        {
16207
            JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
16208
        }
16209
16210
        // check if iterator pos fits to this JSON value
16211
        if (JSON_UNLIKELY(pos.m_object != this))
16212
        {
16213
            JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
16214
        }
16215
16216
        // insert to array and return iterator
16217
        iterator result(this);
16218
        result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist.begin(), ilist.end());
16219
        return result;
16220
    }
16221
16222
    /*!
16223
    @brief inserts elements
16224
16225
    Inserts elements from range `[first, last)`.
16226
16227
    @param[in] first begin of the range of elements to insert
16228
    @param[in] last end of the range of elements to insert
16229
16230
    @throw type_error.309 if called on JSON values other than objects; example:
16231
    `"cannot use insert() with string"`
16232
    @throw invalid_iterator.202 if iterator @a first or @a last does does not
16233
    point to an object; example: `"iterators first and last must point to
16234
    objects"`
16235
    @throw invalid_iterator.210 if @a first and @a last do not belong to the
16236
    same JSON value; example: `"iterators do not fit"`
16237
16238
    @complexity Logarithmic: `O(N*log(size() + N))`, where `N` is the number
16239
    of elements to insert.
16240
16241
    @liveexample{The example shows how `insert()` is used.,insert__range_object}
16242
16243
    @since version 3.0.0
16244
    */
16245
    void insert(const_iterator first, const_iterator last)
16246
    {
16247
        // insert only works for objects
16248
        if (JSON_UNLIKELY(not is_object()))
16249
        {
16250
            JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
16251
        }
16252
16253
        // check if range iterators belong to the same JSON object
16254
        if (JSON_UNLIKELY(first.m_object != last.m_object))
16255
        {
16256
            JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
16257
        }
16258
16259
        // passed iterators must belong to objects
16260
        if (JSON_UNLIKELY(not first.m_object->is_object()))
16261
        {
16262
            JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects"));
16263
        }
16264
16265
        m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
16266
    }
16267
16268
    /*!
16269
    @brief updates a JSON object from another object, overwriting existing keys
16270
16271
    Inserts all values from JSON object @a j and overwrites existing keys.
16272
16273
    @param[in] j  JSON object to read values from
16274
16275
    @throw type_error.312 if called on JSON values other than objects; example:
16276
    `"cannot use update() with string"`
16277
16278
    @complexity O(N*log(size() + N)), where N is the number of elements to
16279
                insert.
16280
16281
    @liveexample{The example shows how `update()` is used.,update}
16282
16283
    @sa https://docs.python.org/3.6/library/stdtypes.html#dict.update
16284
16285
    @since version 3.0.0
16286
    */
16287
    void update(const_reference j)
16288
    {
16289
        // implicitly convert null value to an empty object
16290
        if (is_null())
16291
        {
16292
            m_type = value_t::object;
16293
            m_value.object = create<object_t>();
16294
            assert_invariant();
16295
        }
16296
16297
        if (JSON_UNLIKELY(not is_object()))
16298
        {
16299
            JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name())));
16300
        }
16301
        if (JSON_UNLIKELY(not j.is_object()))
16302
        {
16303
            JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(j.type_name())));
16304
        }
16305
16306
        for (auto it = j.cbegin(); it != j.cend(); ++it)
16307
        {
16308
            m_value.object->operator[](it.key()) = it.value();
16309
        }
16310
    }
16311
16312
    /*!
16313
    @brief updates a JSON object from another object, overwriting existing keys
16314
16315
    Inserts all values from from range `[first, last)` and overwrites existing
16316
    keys.
16317
16318
    @param[in] first begin of the range of elements to insert
16319
    @param[in] last end of the range of elements to insert
16320
16321
    @throw type_error.312 if called on JSON values other than objects; example:
16322
    `"cannot use update() with string"`
16323
    @throw invalid_iterator.202 if iterator @a first or @a last does does not
16324
    point to an object; example: `"iterators first and last must point to
16325
    objects"`
16326
    @throw invalid_iterator.210 if @a first and @a last do not belong to the
16327
    same JSON value; example: `"iterators do not fit"`
16328
16329
    @complexity O(N*log(size() + N)), where N is the number of elements to
16330
                insert.
16331
16332
    @liveexample{The example shows how `update()` is used__range.,update}
16333
16334
    @sa https://docs.python.org/3.6/library/stdtypes.html#dict.update
16335
16336
    @since version 3.0.0
16337
    */
16338
    void update(const_iterator first, const_iterator last)
16339
    {
16340
        // implicitly convert null value to an empty object
16341
        if (is_null())
16342
        {
16343
            m_type = value_t::object;
16344
            m_value.object = create<object_t>();
16345
            assert_invariant();
16346
        }
16347
16348
        if (JSON_UNLIKELY(not is_object()))
16349
        {
16350
            JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name())));
16351
        }
16352
16353
        // check if range iterators belong to the same JSON object
16354
        if (JSON_UNLIKELY(first.m_object != last.m_object))
16355
        {
16356
            JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
16357
        }
16358
16359
        // passed iterators must belong to objects
16360
        if (JSON_UNLIKELY(not first.m_object->is_object()
16361
                          or not last.m_object->is_object()))
16362
        {
16363
            JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects"));
16364
        }
16365
16366
        for (auto it = first; it != last; ++it)
16367
        {
16368
            m_value.object->operator[](it.key()) = it.value();
16369
        }
16370
    }
16371
16372
    /*!
16373
    @brief exchanges the values
16374
16375
    Exchanges the contents of the JSON value with those of @a other. Does not
16376
    invoke any move, copy, or swap operations on individual elements. All
16377
    iterators and references remain valid. The past-the-end iterator is
16378
    invalidated.
16379
16380
    @param[in,out] other JSON value to exchange the contents with
16381
16382
    @complexity Constant.
16383
16384
    @liveexample{The example below shows how JSON values can be swapped with
16385
    `swap()`.,swap__reference}
16386
16387
    @since version 1.0.0
16388
    */
16389
    void swap(reference other) noexcept (
16390
        std::is_nothrow_move_constructible<value_t>::value and
16391
        std::is_nothrow_move_assignable<value_t>::value and
16392
        std::is_nothrow_move_constructible<json_value>::value and
16393
        std::is_nothrow_move_assignable<json_value>::value
16394
    )
16395
0
    {
16396
0
        std::swap(m_type, other.m_type);
16397
0
        std::swap(m_value, other.m_value);
16398
0
        assert_invariant();
16399
0
    }
16400
16401
    /*!
16402
    @brief exchanges the values
16403
16404
    Exchanges the contents of a JSON array with those of @a other. Does not
16405
    invoke any move, copy, or swap operations on individual elements. All
16406
    iterators and references remain valid. The past-the-end iterator is
16407
    invalidated.
16408
16409
    @param[in,out] other array to exchange the contents with
16410
16411
    @throw type_error.310 when JSON value is not an array; example: `"cannot
16412
    use swap() with string"`
16413
16414
    @complexity Constant.
16415
16416
    @liveexample{The example below shows how arrays can be swapped with
16417
    `swap()`.,swap__array_t}
16418
16419
    @since version 1.0.0
16420
    */
16421
    void swap(array_t& other)
16422
    {
16423
        // swap only works for arrays
16424
        if (JSON_LIKELY(is_array()))
16425
        {
16426
            std::swap(*(m_value.array), other);
16427
        }
16428
        else
16429
        {
16430
            JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
16431
        }
16432
    }
16433
16434
    /*!
16435
    @brief exchanges the values
16436
16437
    Exchanges the contents of a JSON object with those of @a other. Does not
16438
    invoke any move, copy, or swap operations on individual elements. All
16439
    iterators and references remain valid. The past-the-end iterator is
16440
    invalidated.
16441
16442
    @param[in,out] other object to exchange the contents with
16443
16444
    @throw type_error.310 when JSON value is not an object; example:
16445
    `"cannot use swap() with string"`
16446
16447
    @complexity Constant.
16448
16449
    @liveexample{The example below shows how objects can be swapped with
16450
    `swap()`.,swap__object_t}
16451
16452
    @since version 1.0.0
16453
    */
16454
    void swap(object_t& other)
16455
    {
16456
        // swap only works for objects
16457
        if (JSON_LIKELY(is_object()))
16458
        {
16459
            std::swap(*(m_value.object), other);
16460
        }
16461
        else
16462
        {
16463
            JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
16464
        }
16465
    }
16466
16467
    /*!
16468
    @brief exchanges the values
16469
16470
    Exchanges the contents of a JSON string with those of @a other. Does not
16471
    invoke any move, copy, or swap operations on individual elements. All
16472
    iterators and references remain valid. The past-the-end iterator is
16473
    invalidated.
16474
16475
    @param[in,out] other string to exchange the contents with
16476
16477
    @throw type_error.310 when JSON value is not a string; example: `"cannot
16478
    use swap() with boolean"`
16479
16480
    @complexity Constant.
16481
16482
    @liveexample{The example below shows how strings can be swapped with
16483
    `swap()`.,swap__string_t}
16484
16485
    @since version 1.0.0
16486
    */
16487
    void swap(string_t& other)
16488
    {
16489
        // swap only works for strings
16490
        if (JSON_LIKELY(is_string()))
16491
        {
16492
            std::swap(*(m_value.string), other);
16493
        }
16494
        else
16495
        {
16496
            JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
16497
        }
16498
    }
16499
16500
    /// @}
16501
16502
  public:
16503
    //////////////////////////////////////////
16504
    // lexicographical comparison operators //
16505
    //////////////////////////////////////////
16506
16507
    /// @name lexicographical comparison operators
16508
    /// @{
16509
16510
    /*!
16511
    @brief comparison: equal
16512
16513
    Compares two JSON values for equality according to the following rules:
16514
    - Two JSON values are equal if (1) they are from the same type and (2)
16515
      their stored values are the same according to their respective
16516
      `operator==`.
16517
    - Integer and floating-point numbers are automatically converted before
16518
      comparison. Note than two NaN values are always treated as unequal.
16519
    - Two JSON null values are equal.
16520
16521
    @note Floating-point inside JSON values numbers are compared with
16522
    `json::number_float_t::operator==` which is `double::operator==` by
16523
    default. To compare floating-point while respecting an epsilon, an alternative
16524
    [comparison function](https://github.com/mariokonrad/marnav/blob/master/src/marnav/math/floatingpoint.hpp#L34-#L39)
16525
    could be used, for instance
16526
    @code {.cpp}
16527
    template<typename T, typename = typename std::enable_if<std::is_floating_point<T>::value, T>::type>
16528
    inline bool is_same(T a, T b, T epsilon = std::numeric_limits<T>::epsilon()) noexcept
16529
    {
16530
        return std::abs(a - b) <= epsilon;
16531
    }
16532
    @endcode
16533
16534
    @note NaN values never compare equal to themselves or to other NaN values.
16535
16536
    @param[in] lhs  first JSON value to consider
16537
    @param[in] rhs  second JSON value to consider
16538
    @return whether the values @a lhs and @a rhs are equal
16539
16540
    @exceptionsafety No-throw guarantee: this function never throws exceptions.
16541
16542
    @complexity Linear.
16543
16544
    @liveexample{The example demonstrates comparing several JSON
16545
    types.,operator__equal}
16546
16547
    @since version 1.0.0
16548
    */
16549
    friend bool operator==(const_reference lhs, const_reference rhs) noexcept
16550
10
    {
16551
10
        const auto lhs_type = lhs.type();
16552
10
        const auto rhs_type = rhs.type();
16553
10
16554
10
        if (lhs_type == rhs_type)
16555
10
        {
16556
10
            switch (lhs_type)
16557
10
            {
16558
10
                case value_t::array:
16559
0
                    return (*lhs.m_value.array == *rhs.m_value.array);
16560
10
16561
10
                case value_t::object:
16562
0
                    return (*lhs.m_value.object == *rhs.m_value.object);
16563
10
16564
10
                case value_t::null:
16565
0
                    return true;
16566
10
16567
10
                case value_t::string:
16568
10
                    return (*lhs.m_value.string == *rhs.m_value.string);
16569
10
16570
10
                case value_t::boolean:
16571
0
                    return (lhs.m_value.boolean == rhs.m_value.boolean);
16572
10
16573
10
                case value_t::number_integer:
16574
0
                    return (lhs.m_value.number_integer == rhs.m_value.number_integer);
16575
10
16576
10
                case value_t::number_unsigned:
16577
0
                    return (lhs.m_value.number_unsigned == rhs.m_value.number_unsigned);
16578
10
16579
10
                case value_t::number_float:
16580
0
                    return (lhs.m_value.number_float == rhs.m_value.number_float);
16581
10
16582
10
                default:
16583
0
                    return false;
16584
0
            }
16585
0
        }
16586
0
        else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
16587
0
        {
16588
0
            return (static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float);
16589
0
        }
16590
0
        else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
16591
0
        {
16592
0
            return (lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer));
16593
0
        }
16594
0
        else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
16595
0
        {
16596
0
            return (static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float);
16597
0
        }
16598
0
        else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
16599
0
        {
16600
0
            return (lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned));
16601
0
        }
16602
0
        else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
16603
0
        {
16604
0
            return (static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer);
16605
0
        }
16606
0
        else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
16607
0
        {
16608
0
            return (lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned));
16609
0
        }
16610
0
16611
0
        return false;
16612
0
    }
16613
16614
    /*!
16615
    @brief comparison: equal
16616
    @copydoc operator==(const_reference, const_reference)
16617
    */
16618
    template<typename ScalarType, typename std::enable_if<
16619
                 std::is_scalar<ScalarType>::value, int>::type = 0>
16620
    friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept
16621
10
    {
16622
10
        return (lhs == basic_json(rhs));
16623
10
    }
16624
16625
    /*!
16626
    @brief comparison: equal
16627
    @copydoc operator==(const_reference, const_reference)
16628
    */
16629
    template<typename ScalarType, typename std::enable_if<
16630
                 std::is_scalar<ScalarType>::value, int>::type = 0>
16631
    friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept
16632
    {
16633
        return (basic_json(lhs) == rhs);
16634
    }
16635
16636
    /*!
16637
    @brief comparison: not equal
16638
16639
    Compares two JSON values for inequality by calculating `not (lhs == rhs)`.
16640
16641
    @param[in] lhs  first JSON value to consider
16642
    @param[in] rhs  second JSON value to consider
16643
    @return whether the values @a lhs and @a rhs are not equal
16644
16645
    @complexity Linear.
16646
16647
    @exceptionsafety No-throw guarantee: this function never throws exceptions.
16648
16649
    @liveexample{The example demonstrates comparing several JSON
16650
    types.,operator__notequal}
16651
16652
    @since version 1.0.0
16653
    */
16654
    friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
16655
    {
16656
        return not (lhs == rhs);
16657
    }
16658
16659
    /*!
16660
    @brief comparison: not equal
16661
    @copydoc operator!=(const_reference, const_reference)
16662
    */
16663
    template<typename ScalarType, typename std::enable_if<
16664
                 std::is_scalar<ScalarType>::value, int>::type = 0>
16665
    friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept
16666
    {
16667
        return (lhs != basic_json(rhs));
16668
    }
16669
16670
    /*!
16671
    @brief comparison: not equal
16672
    @copydoc operator!=(const_reference, const_reference)
16673
    */
16674
    template<typename ScalarType, typename std::enable_if<
16675
                 std::is_scalar<ScalarType>::value, int>::type = 0>
16676
    friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept
16677
    {
16678
        return (basic_json(lhs) != rhs);
16679
    }
16680
16681
    /*!
16682
    @brief comparison: less than
16683
16684
    Compares whether one JSON value @a lhs is less than another JSON value @a
16685
    rhs according to the following rules:
16686
    - If @a lhs and @a rhs have the same type, the values are compared using
16687
      the default `<` operator.
16688
    - Integer and floating-point numbers are automatically converted before
16689
      comparison
16690
    - In case @a lhs and @a rhs have different types, the values are ignored
16691
      and the order of the types is considered, see
16692
      @ref operator<(const value_t, const value_t).
16693
16694
    @param[in] lhs  first JSON value to consider
16695
    @param[in] rhs  second JSON value to consider
16696
    @return whether @a lhs is less than @a rhs
16697
16698
    @complexity Linear.
16699
16700
    @exceptionsafety No-throw guarantee: this function never throws exceptions.
16701
16702
    @liveexample{The example demonstrates comparing several JSON
16703
    types.,operator__less}
16704
16705
    @since version 1.0.0
16706
    */
16707
    friend bool operator<(const_reference lhs, const_reference rhs) noexcept
16708
    {
16709
        const auto lhs_type = lhs.type();
16710
        const auto rhs_type = rhs.type();
16711
16712
        if (lhs_type == rhs_type)
16713
        {
16714
            switch (lhs_type)
16715
            {
16716
                case value_t::array:
16717
                    return (*lhs.m_value.array) < (*rhs.m_value.array);
16718
16719
                case value_t::object:
16720
                    return *lhs.m_value.object < *rhs.m_value.object;
16721
16722
                case value_t::null:
16723
                    return false;
16724
16725
                case value_t::string:
16726
                    return *lhs.m_value.string < *rhs.m_value.string;
16727
16728
                case value_t::boolean:
16729
                    return lhs.m_value.boolean < rhs.m_value.boolean;
16730
16731
                case value_t::number_integer:
16732
                    return lhs.m_value.number_integer < rhs.m_value.number_integer;
16733
16734
                case value_t::number_unsigned:
16735
                    return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
16736
16737
                case value_t::number_float:
16738
                    return lhs.m_value.number_float < rhs.m_value.number_float;
16739
16740
                default:
16741
                    return false;
16742
            }
16743
        }
16744
        else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
16745
        {
16746
            return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
16747
        }
16748
        else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
16749
        {
16750
            return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
16751
        }
16752
        else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
16753
        {
16754
            return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
16755
        }
16756
        else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
16757
        {
16758
            return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
16759
        }
16760
        else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
16761
        {
16762
            return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
16763
        }
16764
        else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
16765
        {
16766
            return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
16767
        }
16768
16769
        // We only reach this line if we cannot compare values. In that case,
16770
        // we compare types. Note we have to call the operator explicitly,
16771
        // because MSVC has problems otherwise.
16772
        return operator<(lhs_type, rhs_type);
16773
    }
16774
16775
    /*!
16776
    @brief comparison: less than
16777
    @copydoc operator<(const_reference, const_reference)
16778
    */
16779
    template<typename ScalarType, typename std::enable_if<
16780
                 std::is_scalar<ScalarType>::value, int>::type = 0>
16781
    friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept
16782
    {
16783
        return (lhs < basic_json(rhs));
16784
    }
16785
16786
    /*!
16787
    @brief comparison: less than
16788
    @copydoc operator<(const_reference, const_reference)
16789
    */
16790
    template<typename ScalarType, typename std::enable_if<
16791
                 std::is_scalar<ScalarType>::value, int>::type = 0>
16792
    friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept
16793
    {
16794
        return (basic_json(lhs) < rhs);
16795
    }
16796
16797
    /*!
16798
    @brief comparison: less than or equal
16799
16800
    Compares whether one JSON value @a lhs is less than or equal to another
16801
    JSON value by calculating `not (rhs < lhs)`.
16802
16803
    @param[in] lhs  first JSON value to consider
16804
    @param[in] rhs  second JSON value to consider
16805
    @return whether @a lhs is less than or equal to @a rhs
16806
16807
    @complexity Linear.
16808
16809
    @exceptionsafety No-throw guarantee: this function never throws exceptions.
16810
16811
    @liveexample{The example demonstrates comparing several JSON
16812
    types.,operator__greater}
16813
16814
    @since version 1.0.0
16815
    */
16816
    friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
16817
    {
16818
        return not (rhs < lhs);
16819
    }
16820
16821
    /*!
16822
    @brief comparison: less than or equal
16823
    @copydoc operator<=(const_reference, const_reference)
16824
    */
16825
    template<typename ScalarType, typename std::enable_if<
16826
                 std::is_scalar<ScalarType>::value, int>::type = 0>
16827
    friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept
16828
    {
16829
        return (lhs <= basic_json(rhs));
16830
    }
16831
16832
    /*!
16833
    @brief comparison: less than or equal
16834
    @copydoc operator<=(const_reference, const_reference)
16835
    */
16836
    template<typename ScalarType, typename std::enable_if<
16837
                 std::is_scalar<ScalarType>::value, int>::type = 0>
16838
    friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept
16839
    {
16840
        return (basic_json(lhs) <= rhs);
16841
    }
16842
16843
    /*!
16844
    @brief comparison: greater than
16845
16846
    Compares whether one JSON value @a lhs is greater than another
16847
    JSON value by calculating `not (lhs <= rhs)`.
16848
16849
    @param[in] lhs  first JSON value to consider
16850
    @param[in] rhs  second JSON value to consider
16851
    @return whether @a lhs is greater than to @a rhs
16852
16853
    @complexity Linear.
16854
16855
    @exceptionsafety No-throw guarantee: this function never throws exceptions.
16856
16857
    @liveexample{The example demonstrates comparing several JSON
16858
    types.,operator__lessequal}
16859
16860
    @since version 1.0.0
16861
    */
16862
    friend bool operator>(const_reference lhs, const_reference rhs) noexcept
16863
    {
16864
        return not (lhs <= rhs);
16865
    }
16866
16867
    /*!
16868
    @brief comparison: greater than
16869
    @copydoc operator>(const_reference, const_reference)
16870
    */
16871
    template<typename ScalarType, typename std::enable_if<
16872
                 std::is_scalar<ScalarType>::value, int>::type = 0>
16873
    friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept
16874
    {
16875
        return (lhs > basic_json(rhs));
16876
    }
16877
16878
    /*!
16879
    @brief comparison: greater than
16880
    @copydoc operator>(const_reference, const_reference)
16881
    */
16882
    template<typename ScalarType, typename std::enable_if<
16883
                 std::is_scalar<ScalarType>::value, int>::type = 0>
16884
    friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept
16885
    {
16886
        return (basic_json(lhs) > rhs);
16887
    }
16888
16889
    /*!
16890
    @brief comparison: greater than or equal
16891
16892
    Compares whether one JSON value @a lhs is greater than or equal to another
16893
    JSON value by calculating `not (lhs < rhs)`.
16894
16895
    @param[in] lhs  first JSON value to consider
16896
    @param[in] rhs  second JSON value to consider
16897
    @return whether @a lhs is greater than or equal to @a rhs
16898
16899
    @complexity Linear.
16900
16901
    @exceptionsafety No-throw guarantee: this function never throws exceptions.
16902
16903
    @liveexample{The example demonstrates comparing several JSON
16904
    types.,operator__greaterequal}
16905
16906
    @since version 1.0.0
16907
    */
16908
    friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
16909
    {
16910
        return not (lhs < rhs);
16911
    }
16912
16913
    /*!
16914
    @brief comparison: greater than or equal
16915
    @copydoc operator>=(const_reference, const_reference)
16916
    */
16917
    template<typename ScalarType, typename std::enable_if<
16918
                 std::is_scalar<ScalarType>::value, int>::type = 0>
16919
    friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept
16920
    {
16921
        return (lhs >= basic_json(rhs));
16922
    }
16923
16924
    /*!
16925
    @brief comparison: greater than or equal
16926
    @copydoc operator>=(const_reference, const_reference)
16927
    */
16928
    template<typename ScalarType, typename std::enable_if<
16929
                 std::is_scalar<ScalarType>::value, int>::type = 0>
16930
    friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept
16931
    {
16932
        return (basic_json(lhs) >= rhs);
16933
    }
16934
16935
    /// @}
16936
16937
    ///////////////////
16938
    // serialization //
16939
    ///////////////////
16940
16941
    /// @name serialization
16942
    /// @{
16943
16944
    /*!
16945
    @brief serialize to stream
16946
16947
    Serialize the given JSON value @a j to the output stream @a o. The JSON
16948
    value will be serialized using the @ref dump member function.
16949
16950
    - The indentation of the output can be controlled with the member variable
16951
      `width` of the output stream @a o. For instance, using the manipulator
16952
      `std::setw(4)` on @a o sets the indentation level to `4` and the
16953
      serialization result is the same as calling `dump(4)`.
16954
16955
    - The indentation character can be controlled with the member variable
16956
      `fill` of the output stream @a o. For instance, the manipulator
16957
      `std::setfill('\\t')` sets indentation to use a tab character rather than
16958
      the default space character.
16959
16960
    @param[in,out] o  stream to serialize to
16961
    @param[in] j  JSON value to serialize
16962
16963
    @return the stream @a o
16964
16965
    @throw type_error.316 if a string stored inside the JSON value is not
16966
                          UTF-8 encoded
16967
16968
    @complexity Linear.
16969
16970
    @liveexample{The example below shows the serialization with different
16971
    parameters to `width` to adjust the indentation level.,operator_serialize}
16972
16973
    @since version 1.0.0; indentation character added in version 3.0.0
16974
    */
16975
    friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
16976
105
    {
16977
105
        // read width member and use it as indentation parameter if nonzero
16978
105
        const bool pretty_print = (o.width() > 0);
16979
105
        const auto indentation = (pretty_print ? o.width() : 0);
16980
105
16981
105
        // reset width to 0 for subsequent calls to this stream
16982
105
        o.width(0);
16983
105
16984
105
        // do the actual serialization
16985
105
        serializer s(detail::output_adapter<char>(o), o.fill());
16986
105
        s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
16987
105
        return o;
16988
105
    }
16989
16990
    /*!
16991
    @brief serialize to stream
16992
    @deprecated This stream operator is deprecated and will be removed in
16993
                future 4.0.0 of the library. Please use
16994
                @ref operator<<(std::ostream&, const basic_json&)
16995
                instead; that is, replace calls like `j >> o;` with `o << j;`.
16996
    @since version 1.0.0; deprecated since version 3.0.0
16997
    */
16998
    JSON_DEPRECATED
16999
    friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
17000
    {
17001
        return o << j;
17002
    }
17003
17004
    /// @}
17005
17006
17007
    /////////////////////
17008
    // deserialization //
17009
    /////////////////////
17010
17011
    /// @name deserialization
17012
    /// @{
17013
17014
    /*!
17015
    @brief deserialize from a compatible input
17016
17017
    This function reads from a compatible input. Examples are:
17018
    - an array of 1-byte values
17019
    - strings with character/literal type with size of 1 byte
17020
    - input streams
17021
    - container with contiguous storage of 1-byte values. Compatible container
17022
      types include `std::vector`, `std::string`, `std::array`,
17023
      `std::valarray`, and `std::initializer_list`. Furthermore, C-style
17024
      arrays can be used with `std::begin()`/`std::end()`. User-defined
17025
      containers can be used as long as they implement random-access iterators
17026
      and a contiguous storage.
17027
17028
    @pre Each element of the container has a size of 1 byte. Violating this
17029
    precondition yields undefined behavior. **This precondition is enforced
17030
    with a static assertion.**
17031
17032
    @pre The container storage is contiguous. Violating this precondition
17033
    yields undefined behavior. **This precondition is enforced with an
17034
    assertion.**
17035
    @pre Each element of the container has a size of 1 byte. Violating this
17036
    precondition yields undefined behavior. **This precondition is enforced
17037
    with a static assertion.**
17038
17039
    @warning There is no way to enforce all preconditions at compile-time. If
17040
             the function is called with a noncompliant container and with
17041
             assertions switched off, the behavior is undefined and will most
17042
             likely yield segmentation violation.
17043
17044
    @param[in] i  input to read from
17045
    @param[in] cb  a parser callback function of type @ref parser_callback_t
17046
    which is used to control the deserialization by filtering unwanted values
17047
    (optional)
17048
17049
    @return result of the deserialization
17050
17051
    @throw parse_error.101 if a parse error occurs; example: `""unexpected end
17052
    of input; expected string literal""`
17053
    @throw parse_error.102 if to_unicode fails or surrogate error
17054
    @throw parse_error.103 if to_unicode fails
17055
17056
    @complexity Linear in the length of the input. The parser is a predictive
17057
    LL(1) parser. The complexity can be higher if the parser callback function
17058
    @a cb has a super-linear complexity.
17059
17060
    @note A UTF-8 byte order mark is silently ignored.
17061
17062
    @liveexample{The example below demonstrates the `parse()` function reading
17063
    from an array.,parse__array__parser_callback_t}
17064
17065
    @liveexample{The example below demonstrates the `parse()` function with
17066
    and without callback function.,parse__string__parser_callback_t}
17067
17068
    @liveexample{The example below demonstrates the `parse()` function with
17069
    and without callback function.,parse__istream__parser_callback_t}
17070
17071
    @liveexample{The example below demonstrates the `parse()` function reading
17072
    from a contiguous container.,parse__contiguouscontainer__parser_callback_t}
17073
17074
    @since version 2.0.3 (contiguous containers)
17075
    */
17076
    static basic_json parse(detail::input_adapter&& i,
17077
                            const parser_callback_t cb = nullptr,
17078
                            const bool allow_exceptions = true)
17079
637
    {
17080
637
        basic_json result;
17081
637
        parser(i, cb, allow_exceptions).parse(true, result);
17082
637
        return result;
17083
637
    }
17084
17085
    static bool accept(detail::input_adapter&& i)
17086
    {
17087
        return parser(i).accept(true);
17088
    }
17089
17090
    /*!
17091
    @brief generate SAX events
17092
17093
    The SAX event lister must follow the interface of @ref json_sax.
17094
17095
    This function reads from a compatible input. Examples are:
17096
    - an array of 1-byte values
17097
    - strings with character/literal type with size of 1 byte
17098
    - input streams
17099
    - container with contiguous storage of 1-byte values. Compatible container
17100
      types include `std::vector`, `std::string`, `std::array`,
17101
      `std::valarray`, and `std::initializer_list`. Furthermore, C-style
17102
      arrays can be used with `std::begin()`/`std::end()`. User-defined
17103
      containers can be used as long as they implement random-access iterators
17104
      and a contiguous storage.
17105
17106
    @pre Each element of the container has a size of 1 byte. Violating this
17107
    precondition yields undefined behavior. **This precondition is enforced
17108
    with a static assertion.**
17109
17110
    @pre The container storage is contiguous. Violating this precondition
17111
    yields undefined behavior. **This precondition is enforced with an
17112
    assertion.**
17113
    @pre Each element of the container has a size of 1 byte. Violating this
17114
    precondition yields undefined behavior. **This precondition is enforced
17115
    with a static assertion.**
17116
17117
    @warning There is no way to enforce all preconditions at compile-time. If
17118
             the function is called with a noncompliant container and with
17119
             assertions switched off, the behavior is undefined and will most
17120
             likely yield segmentation violation.
17121
17122
    @param[in] i  input to read from
17123
    @param[in,out] sax  SAX event listener
17124
    @param[in] format  the format to parse (JSON, CBOR, MessagePack, or UBJSON)
17125
    @param[in] strict  whether the input has to be consumed completely
17126
17127
    @return return value of the last processed SAX event
17128
17129
    @throw parse_error.101 if a parse error occurs; example: `""unexpected end
17130
    of input; expected string literal""`
17131
    @throw parse_error.102 if to_unicode fails or surrogate error
17132
    @throw parse_error.103 if to_unicode fails
17133
17134
    @complexity Linear in the length of the input. The parser is a predictive
17135
    LL(1) parser. The complexity can be higher if the SAX consumer @a sax has
17136
    a super-linear complexity.
17137
17138
    @note A UTF-8 byte order mark is silently ignored.
17139
17140
    @liveexample{The example below demonstrates the `sax_parse()` function
17141
    reading from string and processing the events with a user-defined SAX
17142
    event consumer.,sax_parse}
17143
17144
    @since version 3.2.0
17145
    */
17146
    template <typename SAX>
17147
    static bool sax_parse(detail::input_adapter&& i, SAX* sax,
17148
                          input_format_t format = input_format_t::json,
17149
                          const bool strict = true)
17150
    {
17151
        assert(sax);
17152
        switch (format)
17153
        {
17154
            case input_format_t::json:
17155
                return parser(std::move(i)).sax_parse(sax, strict);
17156
            default:
17157
                return detail::binary_reader<basic_json, SAX>(std::move(i)).sax_parse(format, sax, strict);
17158
        }
17159
    }
17160
17161
    /*!
17162
    @brief deserialize from an iterator range with contiguous storage
17163
17164
    This function reads from an iterator range of a container with contiguous
17165
    storage of 1-byte values. Compatible container types include
17166
    `std::vector`, `std::string`, `std::array`, `std::valarray`, and
17167
    `std::initializer_list`. Furthermore, C-style arrays can be used with
17168
    `std::begin()`/`std::end()`. User-defined containers can be used as long
17169
    as they implement random-access iterators and a contiguous storage.
17170
17171
    @pre The iterator range is contiguous. Violating this precondition yields
17172
    undefined behavior. **This precondition is enforced with an assertion.**
17173
    @pre Each element in the range has a size of 1 byte. Violating this
17174
    precondition yields undefined behavior. **This precondition is enforced
17175
    with a static assertion.**
17176
17177
    @warning There is no way to enforce all preconditions at compile-time. If
17178
             the function is called with noncompliant iterators and with
17179
             assertions switched off, the behavior is undefined and will most
17180
             likely yield segmentation violation.
17181
17182
    @tparam IteratorType iterator of container with contiguous storage
17183
    @param[in] first  begin of the range to parse (included)
17184
    @param[in] last  end of the range to parse (excluded)
17185
    @param[in] cb  a parser callback function of type @ref parser_callback_t
17186
    which is used to control the deserialization by filtering unwanted values
17187
    (optional)
17188
    @param[in] allow_exceptions  whether to throw exceptions in case of a
17189
    parse error (optional, true by default)
17190
17191
    @return result of the deserialization
17192
17193
    @throw parse_error.101 in case of an unexpected token
17194
    @throw parse_error.102 if to_unicode fails or surrogate error
17195
    @throw parse_error.103 if to_unicode fails
17196
17197
    @complexity Linear in the length of the input. The parser is a predictive
17198
    LL(1) parser. The complexity can be higher if the parser callback function
17199
    @a cb has a super-linear complexity.
17200
17201
    @note A UTF-8 byte order mark is silently ignored.
17202
17203
    @liveexample{The example below demonstrates the `parse()` function reading
17204
    from an iterator range.,parse__iteratortype__parser_callback_t}
17205
17206
    @since version 2.0.3
17207
    */
17208
    template<class IteratorType, typename std::enable_if<
17209
                 std::is_base_of<
17210
                     std::random_access_iterator_tag,
17211
                     typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
17212
    static basic_json parse(IteratorType first, IteratorType last,
17213
                            const parser_callback_t cb = nullptr,
17214
                            const bool allow_exceptions = true)
17215
0
    {
17216
0
        basic_json result;
17217
0
        parser(detail::input_adapter(first, last), cb, allow_exceptions).parse(true, result);
17218
0
        return result;
17219
0
    }
17220
17221
    template<class IteratorType, typename std::enable_if<
17222
                 std::is_base_of<
17223
                     std::random_access_iterator_tag,
17224
                     typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
17225
    static bool accept(IteratorType first, IteratorType last)
17226
    {
17227
        return parser(detail::input_adapter(first, last)).accept(true);
17228
    }
17229
17230
    template<class IteratorType, class SAX, typename std::enable_if<
17231
                 std::is_base_of<
17232
                     std::random_access_iterator_tag,
17233
                     typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
17234
    static bool sax_parse(IteratorType first, IteratorType last, SAX* sax)
17235
    {
17236
        return parser(detail::input_adapter(first, last)).sax_parse(sax);
17237
    }
17238
17239
    /*!
17240
    @brief deserialize from stream
17241
    @deprecated This stream operator is deprecated and will be removed in
17242
                version 4.0.0 of the library. Please use
17243
                @ref operator>>(std::istream&, basic_json&)
17244
                instead; that is, replace calls like `j << i;` with `i >> j;`.
17245
    @since version 1.0.0; deprecated since version 3.0.0
17246
    */
17247
    JSON_DEPRECATED
17248
    friend std::istream& operator<<(basic_json& j, std::istream& i)
17249
    {
17250
        return operator>>(i, j);
17251
    }
17252
17253
    /*!
17254
    @brief deserialize from stream
17255
17256
    Deserializes an input stream to a JSON value.
17257
17258
    @param[in,out] i  input stream to read a serialized JSON value from
17259
    @param[in,out] j  JSON value to write the deserialized input to
17260
17261
    @throw parse_error.101 in case of an unexpected token
17262
    @throw parse_error.102 if to_unicode fails or surrogate error
17263
    @throw parse_error.103 if to_unicode fails
17264
17265
    @complexity Linear in the length of the input. The parser is a predictive
17266
    LL(1) parser.
17267
17268
    @note A UTF-8 byte order mark is silently ignored.
17269
17270
    @liveexample{The example below shows how a JSON value is constructed by
17271
    reading a serialization from a stream.,operator_deserialize}
17272
17273
    @sa parse(std::istream&, const parser_callback_t) for a variant with a
17274
    parser callback function to filter values while parsing
17275
17276
    @since version 1.0.0
17277
    */
17278
    friend std::istream& operator>>(std::istream& i, basic_json& j)
17279
198
    {
17280
198
        parser(detail::input_adapter(i)).parse(false, j);
17281
198
        return i;
17282
198
    }
17283
17284
    /// @}
17285
17286
    ///////////////////////////
17287
    // convenience functions //
17288
    ///////////////////////////
17289
17290
    /*!
17291
    @brief return the type as string
17292
17293
    Returns the type name as string to be used in error messages - usually to
17294
    indicate that a function was called on a wrong JSON type.
17295
17296
    @return a string representation of a the @a m_type member:
17297
            Value type  | return value
17298
            ----------- | -------------
17299
            null        | `"null"`
17300
            boolean     | `"boolean"`
17301
            string      | `"string"`
17302
            number      | `"number"` (for all number types)
17303
            object      | `"object"`
17304
            array       | `"array"`
17305
            discarded   | `"discarded"`
17306
17307
    @exceptionsafety No-throw guarantee: this function never throws exceptions.
17308
17309
    @complexity Constant.
17310
17311
    @liveexample{The following code exemplifies `type_name()` for all JSON
17312
    types.,type_name}
17313
17314
    @sa @ref type() -- return the type of the JSON value
17315
    @sa @ref operator value_t() -- return the type of the JSON value (implicit)
17316
17317
    @since version 1.0.0, public since 2.1.0, `const char*` and `noexcept`
17318
    since 3.0.0
17319
    */
17320
    const char* type_name() const noexcept
17321
0
    {
17322
0
        {
17323
0
            switch (m_type)
17324
0
            {
17325
0
                case value_t::null:
17326
0
                    return "null";
17327
0
                case value_t::object:
17328
0
                    return "object";
17329
0
                case value_t::array:
17330
0
                    return "array";
17331
0
                case value_t::string:
17332
0
                    return "string";
17333
0
                case value_t::boolean:
17334
0
                    return "boolean";
17335
0
                case value_t::discarded:
17336
0
                    return "discarded";
17337
0
                default:
17338
0
                    return "number";
17339
0
            }
17340
0
        }
17341
0
    }
17342
17343
17344
  private:
17345
    //////////////////////
17346
    // member variables //
17347
    //////////////////////
17348
17349
    /// the type of the current element
17350
    value_t m_type = value_t::null;
17351
17352
    /// the value of the current element
17353
    json_value m_value = {};
17354
17355
    //////////////////////////////////////////
17356
    // binary serialization/deserialization //
17357
    //////////////////////////////////////////
17358
17359
    /// @name binary serialization/deserialization support
17360
    /// @{
17361
17362
  public:
17363
    /*!
17364
    @brief create a CBOR serialization of a given JSON value
17365
17366
    Serializes a given JSON value @a j to a byte vector using the CBOR (Concise
17367
    Binary Object Representation) serialization format. CBOR is a binary
17368
    serialization format which aims to be more compact than JSON itself, yet
17369
    more efficient to parse.
17370
17371
    The library uses the following mapping from JSON values types to
17372
    CBOR types according to the CBOR specification (RFC 7049):
17373
17374
    JSON value type | value/range                                | CBOR type                          | first byte
17375
    --------------- | ------------------------------------------ | ---------------------------------- | ---------------
17376
    null            | `null`                                     | Null                               | 0xF6
17377
    boolean         | `true`                                     | True                               | 0xF5
17378
    boolean         | `false`                                    | False                              | 0xF4
17379
    number_integer  | -9223372036854775808..-2147483649          | Negative integer (8 bytes follow)  | 0x3B
17380
    number_integer  | -2147483648..-32769                        | Negative integer (4 bytes follow)  | 0x3A
17381
    number_integer  | -32768..-129                               | Negative integer (2 bytes follow)  | 0x39
17382
    number_integer  | -128..-25                                  | Negative integer (1 byte follow)   | 0x38
17383
    number_integer  | -24..-1                                    | Negative integer                   | 0x20..0x37
17384
    number_integer  | 0..23                                      | Integer                            | 0x00..0x17
17385
    number_integer  | 24..255                                    | Unsigned integer (1 byte follow)   | 0x18
17386
    number_integer  | 256..65535                                 | Unsigned integer (2 bytes follow)  | 0x19
17387
    number_integer  | 65536..4294967295                          | Unsigned integer (4 bytes follow)  | 0x1A
17388
    number_integer  | 4294967296..18446744073709551615           | Unsigned integer (8 bytes follow)  | 0x1B
17389
    number_unsigned | 0..23                                      | Integer                            | 0x00..0x17
17390
    number_unsigned | 24..255                                    | Unsigned integer (1 byte follow)   | 0x18
17391
    number_unsigned | 256..65535                                 | Unsigned integer (2 bytes follow)  | 0x19
17392
    number_unsigned | 65536..4294967295                          | Unsigned integer (4 bytes follow)  | 0x1A
17393
    number_unsigned | 4294967296..18446744073709551615           | Unsigned integer (8 bytes follow)  | 0x1B
17394
    number_float    | *any value*                                | Double-Precision Float             | 0xFB
17395
    string          | *length*: 0..23                            | UTF-8 string                       | 0x60..0x77
17396
    string          | *length*: 23..255                          | UTF-8 string (1 byte follow)       | 0x78
17397
    string          | *length*: 256..65535                       | UTF-8 string (2 bytes follow)      | 0x79
17398
    string          | *length*: 65536..4294967295                | UTF-8 string (4 bytes follow)      | 0x7A
17399
    string          | *length*: 4294967296..18446744073709551615 | UTF-8 string (8 bytes follow)      | 0x7B
17400
    array           | *size*: 0..23                              | array                              | 0x80..0x97
17401
    array           | *size*: 23..255                            | array (1 byte follow)              | 0x98
17402
    array           | *size*: 256..65535                         | array (2 bytes follow)             | 0x99
17403
    array           | *size*: 65536..4294967295                  | array (4 bytes follow)             | 0x9A
17404
    array           | *size*: 4294967296..18446744073709551615   | array (8 bytes follow)             | 0x9B
17405
    object          | *size*: 0..23                              | map                                | 0xA0..0xB7
17406
    object          | *size*: 23..255                            | map (1 byte follow)                | 0xB8
17407
    object          | *size*: 256..65535                         | map (2 bytes follow)               | 0xB9
17408
    object          | *size*: 65536..4294967295                  | map (4 bytes follow)               | 0xBA
17409
    object          | *size*: 4294967296..18446744073709551615   | map (8 bytes follow)               | 0xBB
17410
17411
    @note The mapping is **complete** in the sense that any JSON value type
17412
          can be converted to a CBOR value.
17413
17414
    @note If NaN or Infinity are stored inside a JSON number, they are
17415
          serialized properly. This behavior differs from the @ref dump()
17416
          function which serializes NaN or Infinity to `null`.
17417
17418
    @note The following CBOR types are not used in the conversion:
17419
          - byte strings (0x40..0x5F)
17420
          - UTF-8 strings terminated by "break" (0x7F)
17421
          - arrays terminated by "break" (0x9F)
17422
          - maps terminated by "break" (0xBF)
17423
          - date/time (0xC0..0xC1)
17424
          - bignum (0xC2..0xC3)
17425
          - decimal fraction (0xC4)
17426
          - bigfloat (0xC5)
17427
          - tagged items (0xC6..0xD4, 0xD8..0xDB)
17428
          - expected conversions (0xD5..0xD7)
17429
          - simple values (0xE0..0xF3, 0xF8)
17430
          - undefined (0xF7)
17431
          - half and single-precision floats (0xF9-0xFA)
17432
          - break (0xFF)
17433
17434
    @param[in] j  JSON value to serialize
17435
    @return MessagePack serialization as byte vector
17436
17437
    @complexity Linear in the size of the JSON value @a j.
17438
17439
    @liveexample{The example shows the serialization of a JSON value to a byte
17440
    vector in CBOR format.,to_cbor}
17441
17442
    @sa http://cbor.io
17443
    @sa @ref from_cbor(detail::input_adapter, const bool strict) for the
17444
        analogous deserialization
17445
    @sa @ref to_msgpack(const basic_json&) for the related MessagePack format
17446
    @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
17447
             related UBJSON format
17448
17449
    @since version 2.0.9
17450
    */
17451
    static std::vector<uint8_t> to_cbor(const basic_json& j)
17452
    {
17453
        std::vector<uint8_t> result;
17454
        to_cbor(j, result);
17455
        return result;
17456
    }
17457
17458
    static void to_cbor(const basic_json& j, detail::output_adapter<uint8_t> o)
17459
    {
17460
        binary_writer<uint8_t>(o).write_cbor(j);
17461
    }
17462
17463
    static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
17464
    {
17465
        binary_writer<char>(o).write_cbor(j);
17466
    }
17467
17468
    /*!
17469
    @brief create a MessagePack serialization of a given JSON value
17470
17471
    Serializes a given JSON value @a j to a byte vector using the MessagePack
17472
    serialization format. MessagePack is a binary serialization format which
17473
    aims to be more compact than JSON itself, yet more efficient to parse.
17474
17475
    The library uses the following mapping from JSON values types to
17476
    MessagePack types according to the MessagePack specification:
17477
17478
    JSON value type | value/range                       | MessagePack type | first byte
17479
    --------------- | --------------------------------- | ---------------- | ----------
17480
    null            | `null`                            | nil              | 0xC0
17481
    boolean         | `true`                            | true             | 0xC3
17482
    boolean         | `false`                           | false            | 0xC2
17483
    number_integer  | -9223372036854775808..-2147483649 | int64            | 0xD3
17484
    number_integer  | -2147483648..-32769               | int32            | 0xD2
17485
    number_integer  | -32768..-129                      | int16            | 0xD1
17486
    number_integer  | -128..-33                         | int8             | 0xD0
17487
    number_integer  | -32..-1                           | negative fixint  | 0xE0..0xFF
17488
    number_integer  | 0..127                            | positive fixint  | 0x00..0x7F
17489
    number_integer  | 128..255                          | uint 8           | 0xCC
17490
    number_integer  | 256..65535                        | uint 16          | 0xCD
17491
    number_integer  | 65536..4294967295                 | uint 32          | 0xCE
17492
    number_integer  | 4294967296..18446744073709551615  | uint 64          | 0xCF
17493
    number_unsigned | 0..127                            | positive fixint  | 0x00..0x7F
17494
    number_unsigned | 128..255                          | uint 8           | 0xCC
17495
    number_unsigned | 256..65535                        | uint 16          | 0xCD
17496
    number_unsigned | 65536..4294967295                 | uint 32          | 0xCE
17497
    number_unsigned | 4294967296..18446744073709551615  | uint 64          | 0xCF
17498
    number_float    | *any value*                       | float 64         | 0xCB
17499
    string          | *length*: 0..31                   | fixstr           | 0xA0..0xBF
17500
    string          | *length*: 32..255                 | str 8            | 0xD9
17501
    string          | *length*: 256..65535              | str 16           | 0xDA
17502
    string          | *length*: 65536..4294967295       | str 32           | 0xDB
17503
    array           | *size*: 0..15                     | fixarray         | 0x90..0x9F
17504
    array           | *size*: 16..65535                 | array 16         | 0xDC
17505
    array           | *size*: 65536..4294967295         | array 32         | 0xDD
17506
    object          | *size*: 0..15                     | fix map          | 0x80..0x8F
17507
    object          | *size*: 16..65535                 | map 16           | 0xDE
17508
    object          | *size*: 65536..4294967295         | map 32           | 0xDF
17509
17510
    @note The mapping is **complete** in the sense that any JSON value type
17511
          can be converted to a MessagePack value.
17512
17513
    @note The following values can **not** be converted to a MessagePack value:
17514
          - strings with more than 4294967295 bytes
17515
          - arrays with more than 4294967295 elements
17516
          - objects with more than 4294967295 elements
17517
17518
    @note The following MessagePack types are not used in the conversion:
17519
          - bin 8 - bin 32 (0xC4..0xC6)
17520
          - ext 8 - ext 32 (0xC7..0xC9)
17521
          - float 32 (0xCA)
17522
          - fixext 1 - fixext 16 (0xD4..0xD8)
17523
17524
    @note Any MessagePack output created @ref to_msgpack can be successfully
17525
          parsed by @ref from_msgpack.
17526
17527
    @note If NaN or Infinity are stored inside a JSON number, they are
17528
          serialized properly. This behavior differs from the @ref dump()
17529
          function which serializes NaN or Infinity to `null`.
17530
17531
    @param[in] j  JSON value to serialize
17532
    @return MessagePack serialization as byte vector
17533
17534
    @complexity Linear in the size of the JSON value @a j.
17535
17536
    @liveexample{The example shows the serialization of a JSON value to a byte
17537
    vector in MessagePack format.,to_msgpack}
17538
17539
    @sa http://msgpack.org
17540
    @sa @ref from_msgpack(const std::vector<uint8_t>&, const size_t) for the
17541
        analogous deserialization
17542
    @sa @ref to_cbor(const basic_json& for the related CBOR format
17543
    @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
17544
             related UBJSON format
17545
17546
    @since version 2.0.9
17547
    */
17548
    static std::vector<uint8_t> to_msgpack(const basic_json& j)
17549
    {
17550
        std::vector<uint8_t> result;
17551
        to_msgpack(j, result);
17552
        return result;
17553
    }
17554
17555
    static void to_msgpack(const basic_json& j, detail::output_adapter<uint8_t> o)
17556
    {
17557
        binary_writer<uint8_t>(o).write_msgpack(j);
17558
    }
17559
17560
    static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
17561
    {
17562
        binary_writer<char>(o).write_msgpack(j);
17563
    }
17564
17565
    /*!
17566
    @brief create a UBJSON serialization of a given JSON value
17567
17568
    Serializes a given JSON value @a j to a byte vector using the UBJSON
17569
    (Universal Binary JSON) serialization format. UBJSON aims to be more compact
17570
    than JSON itself, yet more efficient to parse.
17571
17572
    The library uses the following mapping from JSON values types to
17573
    UBJSON types according to the UBJSON specification:
17574
17575
    JSON value type | value/range                       | UBJSON type | marker
17576
    --------------- | --------------------------------- | ----------- | ------
17577
    null            | `null`                            | null        | `Z`
17578
    boolean         | `true`                            | true        | `T`
17579
    boolean         | `false`                           | false       | `F`
17580
    number_integer  | -9223372036854775808..-2147483649 | int64       | `L`
17581
    number_integer  | -2147483648..-32769               | int32       | `l`
17582
    number_integer  | -32768..-129                      | int16       | `I`
17583
    number_integer  | -128..127                         | int8        | `i`
17584
    number_integer  | 128..255                          | uint8       | `U`
17585
    number_integer  | 256..32767                        | int16       | `I`
17586
    number_integer  | 32768..2147483647                 | int32       | `l`
17587
    number_integer  | 2147483648..9223372036854775807   | int64       | `L`
17588
    number_unsigned | 0..127                            | int8        | `i`
17589
    number_unsigned | 128..255                          | uint8       | `U`
17590
    number_unsigned | 256..32767                        | int16       | `I`
17591
    number_unsigned | 32768..2147483647                 | int32       | `l`
17592
    number_unsigned | 2147483648..9223372036854775807   | int64       | `L`
17593
    number_float    | *any value*                       | float64     | `D`
17594
    string          | *with shortest length indicator*  | string      | `S`
17595
    array           | *see notes on optimized format*   | array       | `[`
17596
    object          | *see notes on optimized format*   | map         | `{`
17597
17598
    @note The mapping is **complete** in the sense that any JSON value type
17599
          can be converted to a UBJSON value.
17600
17601
    @note The following values can **not** be converted to a UBJSON value:
17602
          - strings with more than 9223372036854775807 bytes (theoretical)
17603
          - unsigned integer numbers above 9223372036854775807
17604
17605
    @note The following markers are not used in the conversion:
17606
          - `Z`: no-op values are not created.
17607
          - `C`: single-byte strings are serialized with `S` markers.
17608
17609
    @note Any UBJSON output created @ref to_ubjson can be successfully parsed
17610
          by @ref from_ubjson.
17611
17612
    @note If NaN or Infinity are stored inside a JSON number, they are
17613
          serialized properly. This behavior differs from the @ref dump()
17614
          function which serializes NaN or Infinity to `null`.
17615
17616
    @note The optimized formats for containers are supported: Parameter
17617
          @a use_size adds size information to the beginning of a container and
17618
          removes the closing marker. Parameter @a use_type further checks
17619
          whether all elements of a container have the same type and adds the
17620
          type marker to the beginning of the container. The @a use_type
17621
          parameter must only be used together with @a use_size = true. Note
17622
          that @a use_size = true alone may result in larger representations -
17623
          the benefit of this parameter is that the receiving side is
17624
          immediately informed on the number of elements of the container.
17625
17626
    @param[in] j  JSON value to serialize
17627
    @param[in] use_size  whether to add size annotations to container types
17628
    @param[in] use_type  whether to add type annotations to container types
17629
                         (must be combined with @a use_size = true)
17630
    @return UBJSON serialization as byte vector
17631
17632
    @complexity Linear in the size of the JSON value @a j.
17633
17634
    @liveexample{The example shows the serialization of a JSON value to a byte
17635
    vector in UBJSON format.,to_ubjson}
17636
17637
    @sa http://ubjson.org
17638
    @sa @ref from_ubjson(detail::input_adapter, const bool strict) for the
17639
        analogous deserialization
17640
    @sa @ref to_cbor(const basic_json& for the related CBOR format
17641
    @sa @ref to_msgpack(const basic_json&) for the related MessagePack format
17642
17643
    @since version 3.1.0
17644
    */
17645
    static std::vector<uint8_t> to_ubjson(const basic_json& j,
17646
                                          const bool use_size = false,
17647
                                          const bool use_type = false)
17648
    {
17649
        std::vector<uint8_t> result;
17650
        to_ubjson(j, result, use_size, use_type);
17651
        return result;
17652
    }
17653
17654
    static void to_ubjson(const basic_json& j, detail::output_adapter<uint8_t> o,
17655
                          const bool use_size = false, const bool use_type = false)
17656
    {
17657
        binary_writer<uint8_t>(o).write_ubjson(j, use_size, use_type);
17658
    }
17659
17660
    static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
17661
                          const bool use_size = false, const bool use_type = false)
17662
    {
17663
        binary_writer<char>(o).write_ubjson(j, use_size, use_type);
17664
    }
17665
17666
    /*!
17667
    @brief create a JSON value from an input in CBOR format
17668
17669
    Deserializes a given input @a i to a JSON value using the CBOR (Concise
17670
    Binary Object Representation) serialization format.
17671
17672
    The library maps CBOR types to JSON value types as follows:
17673
17674
    CBOR type              | JSON value type | first byte
17675
    ---------------------- | --------------- | ----------
17676
    Integer                | number_unsigned | 0x00..0x17
17677
    Unsigned integer       | number_unsigned | 0x18
17678
    Unsigned integer       | number_unsigned | 0x19
17679
    Unsigned integer       | number_unsigned | 0x1A
17680
    Unsigned integer       | number_unsigned | 0x1B
17681
    Negative integer       | number_integer  | 0x20..0x37
17682
    Negative integer       | number_integer  | 0x38
17683
    Negative integer       | number_integer  | 0x39
17684
    Negative integer       | number_integer  | 0x3A
17685
    Negative integer       | number_integer  | 0x3B
17686
    Negative integer       | number_integer  | 0x40..0x57
17687
    UTF-8 string           | string          | 0x60..0x77
17688
    UTF-8 string           | string          | 0x78
17689
    UTF-8 string           | string          | 0x79
17690
    UTF-8 string           | string          | 0x7A
17691
    UTF-8 string           | string          | 0x7B
17692
    UTF-8 string           | string          | 0x7F
17693
    array                  | array           | 0x80..0x97
17694
    array                  | array           | 0x98
17695
    array                  | array           | 0x99
17696
    array                  | array           | 0x9A
17697
    array                  | array           | 0x9B
17698
    array                  | array           | 0x9F
17699
    map                    | object          | 0xA0..0xB7
17700
    map                    | object          | 0xB8
17701
    map                    | object          | 0xB9
17702
    map                    | object          | 0xBA
17703
    map                    | object          | 0xBB
17704
    map                    | object          | 0xBF
17705
    False                  | `false`         | 0xF4
17706
    True                   | `true`          | 0xF5
17707
    Nill                   | `null`          | 0xF6
17708
    Half-Precision Float   | number_float    | 0xF9
17709
    Single-Precision Float | number_float    | 0xFA
17710
    Double-Precision Float | number_float    | 0xFB
17711
17712
    @warning The mapping is **incomplete** in the sense that not all CBOR
17713
             types can be converted to a JSON value. The following CBOR types
17714
             are not supported and will yield parse errors (parse_error.112):
17715
             - byte strings (0x40..0x5F)
17716
             - date/time (0xC0..0xC1)
17717
             - bignum (0xC2..0xC3)
17718
             - decimal fraction (0xC4)
17719
             - bigfloat (0xC5)
17720
             - tagged items (0xC6..0xD4, 0xD8..0xDB)
17721
             - expected conversions (0xD5..0xD7)
17722
             - simple values (0xE0..0xF3, 0xF8)
17723
             - undefined (0xF7)
17724
17725
    @warning CBOR allows map keys of any type, whereas JSON only allows
17726
             strings as keys in object values. Therefore, CBOR maps with keys
17727
             other than UTF-8 strings are rejected (parse_error.113).
17728
17729
    @note Any CBOR output created @ref to_cbor can be successfully parsed by
17730
          @ref from_cbor.
17731
17732
    @param[in] i  an input in CBOR format convertible to an input adapter
17733
    @param[in] strict  whether to expect the input to be consumed until EOF
17734
                       (true by default)
17735
    @param[in] allow_exceptions  whether to throw exceptions in case of a
17736
    parse error (optional, true by default)
17737
17738
    @return deserialized JSON value
17739
17740
    @throw parse_error.110 if the given input ends prematurely or the end of
17741
    file was not reached when @a strict was set to true
17742
    @throw parse_error.112 if unsupported features from CBOR were
17743
    used in the given input @a v or if the input is not valid CBOR
17744
    @throw parse_error.113 if a string was expected as map key, but not found
17745
17746
    @complexity Linear in the size of the input @a i.
17747
17748
    @liveexample{The example shows the deserialization of a byte vector in CBOR
17749
    format to a JSON value.,from_cbor}
17750
17751
    @sa http://cbor.io
17752
    @sa @ref to_cbor(const basic_json&) for the analogous serialization
17753
    @sa @ref from_msgpack(detail::input_adapter, const bool, const bool) for the
17754
        related MessagePack format
17755
    @sa @ref from_ubjson(detail::input_adapter, const bool, const bool) for the
17756
        related UBJSON format
17757
17758
    @since version 2.0.9; parameter @a start_index since 2.1.1; changed to
17759
           consume input adapters, removed start_index parameter, and added
17760
           @a strict parameter since 3.0.0; added @allow_exceptions parameter
17761
           since 3.2.0
17762
    */
17763
    static basic_json from_cbor(detail::input_adapter&& i,
17764
                                const bool strict = true,
17765
                                const bool allow_exceptions = true)
17766
    {
17767
        basic_json result;
17768
        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
17769
        const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::cbor, &sdp, strict);
17770
        return res ? result : basic_json(value_t::discarded);
17771
    }
17772
17773
    /*!
17774
    @copydoc from_cbor(detail::input_adapter, const bool, const bool)
17775
    */
17776
    template<typename A1, typename A2,
17777
             detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
17778
    static basic_json from_cbor(A1 && a1, A2 && a2,
17779
                                const bool strict = true,
17780
                                const bool allow_exceptions = true)
17781
    {
17782
        basic_json result;
17783
        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
17784
        const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::cbor, &sdp, strict);
17785
        return res ? result : basic_json(value_t::discarded);
17786
    }
17787
17788
    /*!
17789
    @brief create a JSON value from an input in MessagePack format
17790
17791
    Deserializes a given input @a i to a JSON value using the MessagePack
17792
    serialization format.
17793
17794
    The library maps MessagePack types to JSON value types as follows:
17795
17796
    MessagePack type | JSON value type | first byte
17797
    ---------------- | --------------- | ----------
17798
    positive fixint  | number_unsigned | 0x00..0x7F
17799
    fixmap           | object          | 0x80..0x8F
17800
    fixarray         | array           | 0x90..0x9F
17801
    fixstr           | string          | 0xA0..0xBF
17802
    nil              | `null`          | 0xC0
17803
    false            | `false`         | 0xC2
17804
    true             | `true`          | 0xC3
17805
    float 32         | number_float    | 0xCA
17806
    float 64         | number_float    | 0xCB
17807
    uint 8           | number_unsigned | 0xCC
17808
    uint 16          | number_unsigned | 0xCD
17809
    uint 32          | number_unsigned | 0xCE
17810
    uint 64          | number_unsigned | 0xCF
17811
    int 8            | number_integer  | 0xD0
17812
    int 16           | number_integer  | 0xD1
17813
    int 32           | number_integer  | 0xD2
17814
    int 64           | number_integer  | 0xD3
17815
    str 8            | string          | 0xD9
17816
    str 16           | string          | 0xDA
17817
    str 32           | string          | 0xDB
17818
    array 16         | array           | 0xDC
17819
    array 32         | array           | 0xDD
17820
    map 16           | object          | 0xDE
17821
    map 32           | object          | 0xDF
17822
    negative fixint  | number_integer  | 0xE0-0xFF
17823
17824
    @warning The mapping is **incomplete** in the sense that not all
17825
             MessagePack types can be converted to a JSON value. The following
17826
             MessagePack types are not supported and will yield parse errors:
17827
              - bin 8 - bin 32 (0xC4..0xC6)
17828
              - ext 8 - ext 32 (0xC7..0xC9)
17829
              - fixext 1 - fixext 16 (0xD4..0xD8)
17830
17831
    @note Any MessagePack output created @ref to_msgpack can be successfully
17832
          parsed by @ref from_msgpack.
17833
17834
    @param[in] i  an input in MessagePack format convertible to an input
17835
                  adapter
17836
    @param[in] strict  whether to expect the input to be consumed until EOF
17837
                       (true by default)
17838
    @param[in] allow_exceptions  whether to throw exceptions in case of a
17839
    parse error (optional, true by default)
17840
17841
    @return deserialized JSON value
17842
17843
    @throw parse_error.110 if the given input ends prematurely or the end of
17844
    file was not reached when @a strict was set to true
17845
    @throw parse_error.112 if unsupported features from MessagePack were
17846
    used in the given input @a i or if the input is not valid MessagePack
17847
    @throw parse_error.113 if a string was expected as map key, but not found
17848
17849
    @complexity Linear in the size of the input @a i.
17850
17851
    @liveexample{The example shows the deserialization of a byte vector in
17852
    MessagePack format to a JSON value.,from_msgpack}
17853
17854
    @sa http://msgpack.org
17855
    @sa @ref to_msgpack(const basic_json&) for the analogous serialization
17856
    @sa @ref from_cbor(detail::input_adapter, const bool, const bool) for the
17857
        related CBOR format
17858
    @sa @ref from_ubjson(detail::input_adapter, const bool, const bool) for
17859
        the related UBJSON format
17860
17861
    @since version 2.0.9; parameter @a start_index since 2.1.1; changed to
17862
           consume input adapters, removed start_index parameter, and added
17863
           @a strict parameter since 3.0.0; added @allow_exceptions parameter
17864
           since 3.2.0
17865
    */
17866
    static basic_json from_msgpack(detail::input_adapter&& i,
17867
                                   const bool strict = true,
17868
                                   const bool allow_exceptions = true)
17869
    {
17870
        basic_json result;
17871
        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
17872
        const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::msgpack, &sdp, strict);
17873
        return res ? result : basic_json(value_t::discarded);
17874
    }
17875
17876
    /*!
17877
    @copydoc from_msgpack(detail::input_adapter, const bool, const bool)
17878
    */
17879
    template<typename A1, typename A2,
17880
             detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
17881
    static basic_json from_msgpack(A1 && a1, A2 && a2,
17882
                                   const bool strict = true,
17883
                                   const bool allow_exceptions = true)
17884
    {
17885
        basic_json result;
17886
        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
17887
        const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::msgpack, &sdp, strict);
17888
        return res ? result : basic_json(value_t::discarded);
17889
    }
17890
17891
    /*!
17892
    @brief create a JSON value from an input in UBJSON format
17893
17894
    Deserializes a given input @a i to a JSON value using the UBJSON (Universal
17895
    Binary JSON) serialization format.
17896
17897
    The library maps UBJSON types to JSON value types as follows:
17898
17899
    UBJSON type | JSON value type                         | marker
17900
    ----------- | --------------------------------------- | ------
17901
    no-op       | *no value, next value is read*          | `N`
17902
    null        | `null`                                  | `Z`
17903
    false       | `false`                                 | `F`
17904
    true        | `true`                                  | `T`
17905
    float32     | number_float                            | `d`
17906
    float64     | number_float                            | `D`
17907
    uint8       | number_unsigned                         | `U`
17908
    int8        | number_integer                          | `i`
17909
    int16       | number_integer                          | `I`
17910
    int32       | number_integer                          | `l`
17911
    int64       | number_integer                          | `L`
17912
    string      | string                                  | `S`
17913
    char        | string                                  | `C`
17914
    array       | array (optimized values are supported)  | `[`
17915
    object      | object (optimized values are supported) | `{`
17916
17917
    @note The mapping is **complete** in the sense that any UBJSON value can
17918
          be converted to a JSON value.
17919
17920
    @param[in] i  an input in UBJSON format convertible to an input adapter
17921
    @param[in] strict  whether to expect the input to be consumed until EOF
17922
                       (true by default)
17923
    @param[in] allow_exceptions  whether to throw exceptions in case of a
17924
    parse error (optional, true by default)
17925
17926
    @return deserialized JSON value
17927
17928
    @throw parse_error.110 if the given input ends prematurely or the end of
17929
    file was not reached when @a strict was set to true
17930
    @throw parse_error.112 if a parse error occurs
17931
    @throw parse_error.113 if a string could not be parsed successfully
17932
17933
    @complexity Linear in the size of the input @a i.
17934
17935
    @liveexample{The example shows the deserialization of a byte vector in
17936
    UBJSON format to a JSON value.,from_ubjson}
17937
17938
    @sa http://ubjson.org
17939
    @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
17940
             analogous serialization
17941
    @sa @ref from_cbor(detail::input_adapter, const bool, const bool) for the
17942
        related CBOR format
17943
    @sa @ref from_msgpack(detail::input_adapter, const bool, const bool) for
17944
        the related MessagePack format
17945
17946
    @since version 3.1.0; added @allow_exceptions parameter since 3.2.0
17947
    */
17948
    static basic_json from_ubjson(detail::input_adapter&& i,
17949
                                  const bool strict = true,
17950
                                  const bool allow_exceptions = true)
17951
    {
17952
        basic_json result;
17953
        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
17954
        const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::ubjson, &sdp, strict);
17955
        return res ? result : basic_json(value_t::discarded);
17956
    }
17957
17958
    /*!
17959
    @copydoc from_ubjson(detail::input_adapter, const bool, const bool)
17960
    */
17961
    template<typename A1, typename A2,
17962
             detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
17963
    static basic_json from_ubjson(A1 && a1, A2 && a2,
17964
                                  const bool strict = true,
17965
                                  const bool allow_exceptions = true)
17966
    {
17967
        basic_json result;
17968
        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
17969
        const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::ubjson, &sdp, strict);
17970
        return res ? result : basic_json(value_t::discarded);
17971
    }
17972
17973
    /// @}
17974
17975
    //////////////////////////
17976
    // JSON Pointer support //
17977
    //////////////////////////
17978
17979
    /// @name JSON Pointer functions
17980
    /// @{
17981
17982
    /*!
17983
    @brief access specified element via JSON Pointer
17984
17985
    Uses a JSON pointer to retrieve a reference to the respective JSON value.
17986
    No bound checking is performed. Similar to @ref operator[](const typename
17987
    object_t::key_type&), `null` values are created in arrays and objects if
17988
    necessary.
17989
17990
    In particular:
17991
    - If the JSON pointer points to an object key that does not exist, it
17992
      is created an filled with a `null` value before a reference to it
17993
      is returned.
17994
    - If the JSON pointer points to an array index that does not exist, it
17995
      is created an filled with a `null` value before a reference to it
17996
      is returned. All indices between the current maximum and the given
17997
      index are also filled with `null`.
17998
    - The special value `-` is treated as a synonym for the index past the
17999
      end.
18000
18001
    @param[in] ptr  a JSON pointer
18002
18003
    @return reference to the element pointed to by @a ptr
18004
18005
    @complexity Constant.
18006
18007
    @throw parse_error.106   if an array index begins with '0'
18008
    @throw parse_error.109   if an array index was not a number
18009
    @throw out_of_range.404  if the JSON pointer can not be resolved
18010
18011
    @liveexample{The behavior is shown in the example.,operatorjson_pointer}
18012
18013
    @since version 2.0.0
18014
    */
18015
    reference operator[](const json_pointer& ptr)
18016
    {
18017
        return ptr.get_unchecked(this);
18018
    }
18019
18020
    /*!
18021
    @brief access specified element via JSON Pointer
18022
18023
    Uses a JSON pointer to retrieve a reference to the respective JSON value.
18024
    No bound checking is performed. The function does not change the JSON
18025
    value; no `null` values are created. In particular, the the special value
18026
    `-` yields an exception.
18027
18028
    @param[in] ptr  JSON pointer to the desired element
18029
18030
    @return const reference to the element pointed to by @a ptr
18031
18032
    @complexity Constant.
18033
18034
    @throw parse_error.106   if an array index begins with '0'
18035
    @throw parse_error.109   if an array index was not a number
18036
    @throw out_of_range.402  if the array index '-' is used
18037
    @throw out_of_range.404  if the JSON pointer can not be resolved
18038
18039
    @liveexample{The behavior is shown in the example.,operatorjson_pointer_const}
18040
18041
    @since version 2.0.0
18042
    */
18043
    const_reference operator[](const json_pointer& ptr) const
18044
    {
18045
        return ptr.get_unchecked(this);
18046
    }
18047
18048
    /*!
18049
    @brief access specified element via JSON Pointer
18050
18051
    Returns a reference to the element at with specified JSON pointer @a ptr,
18052
    with bounds checking.
18053
18054
    @param[in] ptr  JSON pointer to the desired element
18055
18056
    @return reference to the element pointed to by @a ptr
18057
18058
    @throw parse_error.106 if an array index in the passed JSON pointer @a ptr
18059
    begins with '0'. See example below.
18060
18061
    @throw parse_error.109 if an array index in the passed JSON pointer @a ptr
18062
    is not a number. See example below.
18063
18064
    @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr
18065
    is out of range. See example below.
18066
18067
    @throw out_of_range.402 if the array index '-' is used in the passed JSON
18068
    pointer @a ptr. As `at` provides checked access (and no elements are
18069
    implicitly inserted), the index '-' is always invalid. See example below.
18070
18071
    @throw out_of_range.403 if the JSON pointer describes a key of an object
18072
    which cannot be found. See example below.
18073
18074
    @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved.
18075
    See example below.
18076
18077
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
18078
    changes in the JSON value.
18079
18080
    @complexity Constant.
18081
18082
    @since version 2.0.0
18083
18084
    @liveexample{The behavior is shown in the example.,at_json_pointer}
18085
    */
18086
    reference at(const json_pointer& ptr)
18087
    {
18088
        return ptr.get_checked(this);
18089
    }
18090
18091
    /*!
18092
    @brief access specified element via JSON Pointer
18093
18094
    Returns a const reference to the element at with specified JSON pointer @a
18095
    ptr, with bounds checking.
18096
18097
    @param[in] ptr  JSON pointer to the desired element
18098
18099
    @return reference to the element pointed to by @a ptr
18100
18101
    @throw parse_error.106 if an array index in the passed JSON pointer @a ptr
18102
    begins with '0'. See example below.
18103
18104
    @throw parse_error.109 if an array index in the passed JSON pointer @a ptr
18105
    is not a number. See example below.
18106
18107
    @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr
18108
    is out of range. See example below.
18109
18110
    @throw out_of_range.402 if the array index '-' is used in the passed JSON
18111
    pointer @a ptr. As `at` provides checked access (and no elements are
18112
    implicitly inserted), the index '-' is always invalid. See example below.
18113
18114
    @throw out_of_range.403 if the JSON pointer describes a key of an object
18115
    which cannot be found. See example below.
18116
18117
    @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved.
18118
    See example below.
18119
18120
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
18121
    changes in the JSON value.
18122
18123
    @complexity Constant.
18124
18125
    @since version 2.0.0
18126
18127
    @liveexample{The behavior is shown in the example.,at_json_pointer_const}
18128
    */
18129
    const_reference at(const json_pointer& ptr) const
18130
    {
18131
        return ptr.get_checked(this);
18132
    }
18133
18134
    /*!
18135
    @brief return flattened JSON value
18136
18137
    The function creates a JSON object whose keys are JSON pointers (see [RFC
18138
    6901](https://tools.ietf.org/html/rfc6901)) and whose values are all
18139
    primitive. The original JSON value can be restored using the @ref
18140
    unflatten() function.
18141
18142
    @return an object that maps JSON pointers to primitive values
18143
18144
    @note Empty objects and arrays are flattened to `null` and will not be
18145
          reconstructed correctly by the @ref unflatten() function.
18146
18147
    @complexity Linear in the size the JSON value.
18148
18149
    @liveexample{The following code shows how a JSON object is flattened to an
18150
    object whose keys consist of JSON pointers.,flatten}
18151
18152
    @sa @ref unflatten() for the reverse function
18153
18154
    @since version 2.0.0
18155
    */
18156
    basic_json flatten() const
18157
    {
18158
        basic_json result(value_t::object);
18159
        json_pointer::flatten("", *this, result);
18160
        return result;
18161
    }
18162
18163
    /*!
18164
    @brief unflatten a previously flattened JSON value
18165
18166
    The function restores the arbitrary nesting of a JSON value that has been
18167
    flattened before using the @ref flatten() function. The JSON value must
18168
    meet certain constraints:
18169
    1. The value must be an object.
18170
    2. The keys must be JSON pointers (see
18171
       [RFC 6901](https://tools.ietf.org/html/rfc6901))
18172
    3. The mapped values must be primitive JSON types.
18173
18174
    @return the original JSON from a flattened version
18175
18176
    @note Empty objects and arrays are flattened by @ref flatten() to `null`
18177
          values and can not unflattened to their original type. Apart from
18178
          this example, for a JSON value `j`, the following is always true:
18179
          `j == j.flatten().unflatten()`.
18180
18181
    @complexity Linear in the size the JSON value.
18182
18183
    @throw type_error.314  if value is not an object
18184
    @throw type_error.315  if object values are not primitive
18185
18186
    @liveexample{The following code shows how a flattened JSON object is
18187
    unflattened into the original nested JSON object.,unflatten}
18188
18189
    @sa @ref flatten() for the reverse function
18190
18191
    @since version 2.0.0
18192
    */
18193
    basic_json unflatten() const
18194
    {
18195
        return json_pointer::unflatten(*this);
18196
    }
18197
18198
    /// @}
18199
18200
    //////////////////////////
18201
    // JSON Patch functions //
18202
    //////////////////////////
18203
18204
    /// @name JSON Patch functions
18205
    /// @{
18206
18207
    /*!
18208
    @brief applies a JSON patch
18209
18210
    [JSON Patch](http://jsonpatch.com) defines a JSON document structure for
18211
    expressing a sequence of operations to apply to a JSON) document. With
18212
    this function, a JSON Patch is applied to the current JSON value by
18213
    executing all operations from the patch.
18214
18215
    @param[in] json_patch  JSON patch document
18216
    @return patched document
18217
18218
    @note The application of a patch is atomic: Either all operations succeed
18219
          and the patched document is returned or an exception is thrown. In
18220
          any case, the original value is not changed: the patch is applied
18221
          to a copy of the value.
18222
18223
    @throw parse_error.104 if the JSON patch does not consist of an array of
18224
    objects
18225
18226
    @throw parse_error.105 if the JSON patch is malformed (e.g., mandatory
18227
    attributes are missing); example: `"operation add must have member path"`
18228
18229
    @throw out_of_range.401 if an array index is out of range.
18230
18231
    @throw out_of_range.403 if a JSON pointer inside the patch could not be
18232
    resolved successfully in the current JSON value; example: `"key baz not
18233
    found"`
18234
18235
    @throw out_of_range.405 if JSON pointer has no parent ("add", "remove",
18236
    "move")
18237
18238
    @throw other_error.501 if "test" operation was unsuccessful
18239
18240
    @complexity Linear in the size of the JSON value and the length of the
18241
    JSON patch. As usually only a fraction of the JSON value is affected by
18242
    the patch, the complexity can usually be neglected.
18243
18244
    @liveexample{The following code shows how a JSON patch is applied to a
18245
    value.,patch}
18246
18247
    @sa @ref diff -- create a JSON patch by comparing two JSON values
18248
18249
    @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902)
18250
    @sa [RFC 6901 (JSON Pointer)](https://tools.ietf.org/html/rfc6901)
18251
18252
    @since version 2.0.0
18253
    */
18254
    basic_json patch(const basic_json& json_patch) const
18255
    {
18256
        // make a working copy to apply the patch to
18257
        basic_json result = *this;
18258
18259
        // the valid JSON Patch operations
18260
        enum class patch_operations {add, remove, replace, move, copy, test, invalid};
18261
18262
        const auto get_op = [](const std::string & op)
18263
        {
18264
            if (op == "add")
18265
            {
18266
                return patch_operations::add;
18267
            }
18268
            if (op == "remove")
18269
            {
18270
                return patch_operations::remove;
18271
            }
18272
            if (op == "replace")
18273
            {
18274
                return patch_operations::replace;
18275
            }
18276
            if (op == "move")
18277
            {
18278
                return patch_operations::move;
18279
            }
18280
            if (op == "copy")
18281
            {
18282
                return patch_operations::copy;
18283
            }
18284
            if (op == "test")
18285
            {
18286
                return patch_operations::test;
18287
            }
18288
18289
            return patch_operations::invalid;
18290
        };
18291
18292
        // wrapper for "add" operation; add value at ptr
18293
        const auto operation_add = [&result](json_pointer & ptr, basic_json val)
18294
        {
18295
            // adding to the root of the target document means replacing it
18296
            if (ptr.is_root())
18297
            {
18298
                result = val;
18299
            }
18300
            else
18301
            {
18302
                // make sure the top element of the pointer exists
18303
                json_pointer top_pointer = ptr.top();
18304
                if (top_pointer != ptr)
18305
                {
18306
                    result.at(top_pointer);
18307
                }
18308
18309
                // get reference to parent of JSON pointer ptr
18310
                const auto last_path = ptr.pop_back();
18311
                basic_json& parent = result[ptr];
18312
18313
                switch (parent.m_type)
18314
                {
18315
                    case value_t::null:
18316
                    case value_t::object:
18317
                    {
18318
                        // use operator[] to add value
18319
                        parent[last_path] = val;
18320
                        break;
18321
                    }
18322
18323
                    case value_t::array:
18324
                    {
18325
                        if (last_path == "-")
18326
                        {
18327
                            // special case: append to back
18328
                            parent.push_back(val);
18329
                        }
18330
                        else
18331
                        {
18332
                            const auto idx = json_pointer::array_index(last_path);
18333
                            if (JSON_UNLIKELY(static_cast<size_type>(idx) > parent.size()))
18334
                            {
18335
                                // avoid undefined behavior
18336
                                JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
18337
                            }
18338
                            else
18339
                            {
18340
                                // default case: insert add offset
18341
                                parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
18342
                            }
18343
                        }
18344
                        break;
18345
                    }
18346
18347
                    // LCOV_EXCL_START
18348
                    default:
18349
                    {
18350
                        // if there exists a parent it cannot be primitive
18351
                        assert(false);
18352
                    }
18353
                        // LCOV_EXCL_STOP
18354
                }
18355
            }
18356
        };
18357
18358
        // wrapper for "remove" operation; remove value at ptr
18359
        const auto operation_remove = [&result](json_pointer & ptr)
18360
        {
18361
            // get reference to parent of JSON pointer ptr
18362
            const auto last_path = ptr.pop_back();
18363
            basic_json& parent = result.at(ptr);
18364
18365
            // remove child
18366
            if (parent.is_object())
18367
            {
18368
                // perform range check
18369
                auto it = parent.find(last_path);
18370
                if (JSON_LIKELY(it != parent.end()))
18371
                {
18372
                    parent.erase(it);
18373
                }
18374
                else
18375
                {
18376
                    JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found"));
18377
                }
18378
            }
18379
            else if (parent.is_array())
18380
            {
18381
                // note erase performs range check
18382
                parent.erase(static_cast<size_type>(json_pointer::array_index(last_path)));
18383
            }
18384
        };
18385
18386
        // type check: top level value must be an array
18387
        if (JSON_UNLIKELY(not json_patch.is_array()))
18388
        {
18389
            JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects"));
18390
        }
18391
18392
        // iterate and apply the operations
18393
        for (const auto& val : json_patch)
18394
        {
18395
            // wrapper to get a value for an operation
18396
            const auto get_value = [&val](const std::string & op,
18397
                                          const std::string & member,
18398
                                          bool string_type) -> basic_json &
18399
            {
18400
                // find value
18401
                auto it = val.m_value.object->find(member);
18402
18403
                // context-sensitive error message
18404
                const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
18405
18406
                // check if desired value is present
18407
                if (JSON_UNLIKELY(it == val.m_value.object->end()))
18408
                {
18409
                    JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'"));
18410
                }
18411
18412
                // check if result is of type string
18413
                if (JSON_UNLIKELY(string_type and not it->second.is_string()))
18414
                {
18415
                    JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'"));
18416
                }
18417
18418
                // no error: return value
18419
                return it->second;
18420
            };
18421
18422
            // type check: every element of the array must be an object
18423
            if (JSON_UNLIKELY(not val.is_object()))
18424
            {
18425
                JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects"));
18426
            }
18427
18428
            // collect mandatory members
18429
            const std::string op = get_value("op", "op", true);
18430
            const std::string path = get_value(op, "path", true);
18431
            json_pointer ptr(path);
18432
18433
            switch (get_op(op))
18434
            {
18435
                case patch_operations::add:
18436
                {
18437
                    operation_add(ptr, get_value("add", "value", false));
18438
                    break;
18439
                }
18440
18441
                case patch_operations::remove:
18442
                {
18443
                    operation_remove(ptr);
18444
                    break;
18445
                }
18446
18447
                case patch_operations::replace:
18448
                {
18449
                    // the "path" location must exist - use at()
18450
                    result.at(ptr) = get_value("replace", "value", false);
18451
                    break;
18452
                }
18453
18454
                case patch_operations::move:
18455
                {
18456
                    const std::string from_path = get_value("move", "from", true);
18457
                    json_pointer from_ptr(from_path);
18458
18459
                    // the "from" location must exist - use at()
18460
                    basic_json v = result.at(from_ptr);
18461
18462
                    // The move operation is functionally identical to a
18463
                    // "remove" operation on the "from" location, followed
18464
                    // immediately by an "add" operation at the target
18465
                    // location with the value that was just removed.
18466
                    operation_remove(from_ptr);
18467
                    operation_add(ptr, v);
18468
                    break;
18469
                }
18470
18471
                case patch_operations::copy:
18472
                {
18473
                    const std::string from_path = get_value("copy", "from", true);
18474
                    const json_pointer from_ptr(from_path);
18475
18476
                    // the "from" location must exist - use at()
18477
                    basic_json v = result.at(from_ptr);
18478
18479
                    // The copy is functionally identical to an "add"
18480
                    // operation at the target location using the value
18481
                    // specified in the "from" member.
18482
                    operation_add(ptr, v);
18483
                    break;
18484
                }
18485
18486
                case patch_operations::test:
18487
                {
18488
                    bool success = false;
18489
                    JSON_TRY
18490
                    {
18491
                        // check if "value" matches the one at "path"
18492
                        // the "path" location must exist - use at()
18493
                        success = (result.at(ptr) == get_value("test", "value", false));
18494
                    }
18495
                    JSON_INTERNAL_CATCH (out_of_range&)
18496
                    {
18497
                        // ignore out of range errors: success remains false
18498
                    }
18499
18500
                    // throw an exception if test fails
18501
                    if (JSON_UNLIKELY(not success))
18502
                    {
18503
                        JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump()));
18504
                    }
18505
18506
                    break;
18507
                }
18508
18509
                case patch_operations::invalid:
18510
                {
18511
                    // op must be "add", "remove", "replace", "move", "copy", or
18512
                    // "test"
18513
                    JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid"));
18514
                }
18515
            }
18516
        }
18517
18518
        return result;
18519
    }
18520
18521
    /*!
18522
    @brief creates a diff as a JSON patch
18523
18524
    Creates a [JSON Patch](http://jsonpatch.com) so that value @a source can
18525
    be changed into the value @a target by calling @ref patch function.
18526
18527
    @invariant For two JSON values @a source and @a target, the following code
18528
    yields always `true`:
18529
    @code {.cpp}
18530
    source.patch(diff(source, target)) == target;
18531
    @endcode
18532
18533
    @note Currently, only `remove`, `add`, and `replace` operations are
18534
          generated.
18535
18536
    @param[in] source  JSON value to compare from
18537
    @param[in] target  JSON value to compare against
18538
    @param[in] path    helper value to create JSON pointers
18539
18540
    @return a JSON patch to convert the @a source to @a target
18541
18542
    @complexity Linear in the lengths of @a source and @a target.
18543
18544
    @liveexample{The following code shows how a JSON patch is created as a
18545
    diff for two JSON values.,diff}
18546
18547
    @sa @ref patch -- apply a JSON patch
18548
    @sa @ref merge_patch -- apply a JSON Merge Patch
18549
18550
    @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902)
18551
18552
    @since version 2.0.0
18553
    */
18554
    static basic_json diff(const basic_json& source, const basic_json& target,
18555
                           const std::string& path = "")
18556
    {
18557
        // the patch
18558
        basic_json result(value_t::array);
18559
18560
        // if the values are the same, return empty patch
18561
        if (source == target)
18562
        {
18563
            return result;
18564
        }
18565
18566
        if (source.type() != target.type())
18567
        {
18568
            // different types: replace value
18569
            result.push_back(
18570
            {
18571
                {"op", "replace"}, {"path", path}, {"value", target}
18572
            });
18573
        }
18574
        else
18575
        {
18576
            switch (source.type())
18577
            {
18578
                case value_t::array:
18579
                {
18580
                    // first pass: traverse common elements
18581
                    std::size_t i = 0;
18582
                    while (i < source.size() and i < target.size())
18583
                    {
18584
                        // recursive call to compare array values at index i
18585
                        auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
18586
                        result.insert(result.end(), temp_diff.begin(), temp_diff.end());
18587
                        ++i;
18588
                    }
18589
18590
                    // i now reached the end of at least one array
18591
                    // in a second pass, traverse the remaining elements
18592
18593
                    // remove my remaining elements
18594
                    const auto end_index = static_cast<difference_type>(result.size());
18595
                    while (i < source.size())
18596
                    {
18597
                        // add operations in reverse order to avoid invalid
18598
                        // indices
18599
                        result.insert(result.begin() + end_index, object(
18600
                        {
18601
                            {"op", "remove"},
18602
                            {"path", path + "/" + std::to_string(i)}
18603
                        }));
18604
                        ++i;
18605
                    }
18606
18607
                    // add other remaining elements
18608
                    while (i < target.size())
18609
                    {
18610
                        result.push_back(
18611
                        {
18612
                            {"op", "add"},
18613
                            {"path", path + "/" + std::to_string(i)},
18614
                            {"value", target[i]}
18615
                        });
18616
                        ++i;
18617
                    }
18618
18619
                    break;
18620
                }
18621
18622
                case value_t::object:
18623
                {
18624
                    // first pass: traverse this object's elements
18625
                    for (auto it = source.cbegin(); it != source.cend(); ++it)
18626
                    {
18627
                        // escape the key name to be used in a JSON patch
18628
                        const auto key = json_pointer::escape(it.key());
18629
18630
                        if (target.find(it.key()) != target.end())
18631
                        {
18632
                            // recursive call to compare object values at key it
18633
                            auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key);
18634
                            result.insert(result.end(), temp_diff.begin(), temp_diff.end());
18635
                        }
18636
                        else
18637
                        {
18638
                            // found a key that is not in o -> remove it
18639
                            result.push_back(object(
18640
                            {
18641
                                {"op", "remove"}, {"path", path + "/" + key}
18642
                            }));
18643
                        }
18644
                    }
18645
18646
                    // second pass: traverse other object's elements
18647
                    for (auto it = target.cbegin(); it != target.cend(); ++it)
18648
                    {
18649
                        if (source.find(it.key()) == source.end())
18650
                        {
18651
                            // found a key that is not in this -> add it
18652
                            const auto key = json_pointer::escape(it.key());
18653
                            result.push_back(
18654
                            {
18655
                                {"op", "add"}, {"path", path + "/" + key},
18656
                                {"value", it.value()}
18657
                            });
18658
                        }
18659
                    }
18660
18661
                    break;
18662
                }
18663
18664
                default:
18665
                {
18666
                    // both primitive type: replace value
18667
                    result.push_back(
18668
                    {
18669
                        {"op", "replace"}, {"path", path}, {"value", target}
18670
                    });
18671
                    break;
18672
                }
18673
            }
18674
        }
18675
18676
        return result;
18677
    }
18678
18679
    /// @}
18680
18681
    ////////////////////////////////
18682
    // JSON Merge Patch functions //
18683
    ////////////////////////////////
18684
18685
    /// @name JSON Merge Patch functions
18686
    /// @{
18687
18688
    /*!
18689
    @brief applies a JSON Merge Patch
18690
18691
    The merge patch format is primarily intended for use with the HTTP PATCH
18692
    method as a means of describing a set of modifications to a target
18693
    resource's content. This function applies a merge patch to the current
18694
    JSON value.
18695
18696
    The function implements the following algorithm from Section 2 of
18697
    [RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396):
18698
18699
    ```
18700
    define MergePatch(Target, Patch):
18701
      if Patch is an Object:
18702
        if Target is not an Object:
18703
          Target = {} // Ignore the contents and set it to an empty Object
18704
        for each Name/Value pair in Patch:
18705
          if Value is null:
18706
            if Name exists in Target:
18707
              remove the Name/Value pair from Target
18708
          else:
18709
            Target[Name] = MergePatch(Target[Name], Value)
18710
        return Target
18711
      else:
18712
        return Patch
18713
    ```
18714
18715
    Thereby, `Target` is the current object; that is, the patch is applied to
18716
    the current value.
18717
18718
    @param[in] patch  the patch to apply
18719
18720
    @complexity Linear in the lengths of @a patch.
18721
18722
    @liveexample{The following code shows how a JSON Merge Patch is applied to
18723
    a JSON document.,merge_patch}
18724
18725
    @sa @ref patch -- apply a JSON patch
18726
    @sa [RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396)
18727
18728
    @since version 3.0.0
18729
    */
18730
    void merge_patch(const basic_json& patch)
18731
    {
18732
        if (patch.is_object())
18733
        {
18734
            if (not is_object())
18735
            {
18736
                *this = object();
18737
            }
18738
            for (auto it = patch.begin(); it != patch.end(); ++it)
18739
            {
18740
                if (it.value().is_null())
18741
                {
18742
                    erase(it.key());
18743
                }
18744
                else
18745
                {
18746
                    operator[](it.key()).merge_patch(it.value());
18747
                }
18748
            }
18749
        }
18750
        else
18751
        {
18752
            *this = patch;
18753
        }
18754
    }
18755
18756
    /// @}
18757
};
18758
} // namespace nlohmann
18759
18760
///////////////////////
18761
// nonmember support //
18762
///////////////////////
18763
18764
// specialization of std::swap, and std::hash
18765
namespace std
18766
{
18767
18768
/// hash value for JSON objects
18769
template<>
18770
struct hash<nlohmann::json>
18771
{
18772
    /*!
18773
    @brief return a hash value for a JSON object
18774
18775
    @since version 1.0.0
18776
    */
18777
    std::size_t operator()(const nlohmann::json& j) const
18778
0
    {
18779
0
        // a naive hashing via the string representation
18780
0
        const auto& h = hash<nlohmann::json::string_t>();
18781
0
        return h(j.dump());
18782
0
    }
18783
};
18784
18785
/// specialization for std::less<value_t>
18786
/// @note: do not remove the space after '<',
18787
///        see https://github.com/nlohmann/json/pull/679
18788
template<>
18789
struct less< ::nlohmann::detail::value_t>
18790
{
18791
    /*!
18792
    @brief compare two value_t enum values
18793
    @since version 3.0.0
18794
    */
18795
    bool operator()(nlohmann::detail::value_t lhs,
18796
                    nlohmann::detail::value_t rhs) const noexcept
18797
0
    {
18798
0
        return nlohmann::detail::operator<(lhs, rhs);
18799
0
    }
18800
};
18801
18802
/*!
18803
@brief exchanges the values of two JSON objects
18804
18805
@since version 1.0.0
18806
*/
18807
template<>
18808
inline void swap<nlohmann::json>(nlohmann::json& j1, nlohmann::json& j2) noexcept(
18809
    is_nothrow_move_constructible<nlohmann::json>::value and
18810
    is_nothrow_move_assignable<nlohmann::json>::value
18811
)
18812
0
{
18813
0
    j1.swap(j2);
18814
0
}
18815
18816
} // namespace std
18817
18818
/*!
18819
@brief user-defined string literal for JSON values
18820
18821
This operator implements a user-defined string literal for JSON objects. It
18822
can be used by adding `"_json"` to a string literal and returns a JSON object
18823
if no parse error occurred.
18824
18825
@param[in] s  a string representation of a JSON object
18826
@param[in] n  the length of string @a s
18827
@return a JSON object
18828
18829
@since version 1.0.0
18830
*/
18831
inline nlohmann::json operator "" _json(const char* s, std::size_t n)
18832
0
{
18833
0
    return nlohmann::json::parse(s, s + n);
18834
0
}
18835
18836
/*!
18837
@brief user-defined string literal for JSON pointer
18838
18839
This operator implements a user-defined string literal for JSON Pointers. It
18840
can be used by adding `"_json_pointer"` to a string literal and returns a JSON pointer
18841
object if no parse error occurred.
18842
18843
@param[in] s  a string representation of a JSON Pointer
18844
@param[in] n  the length of string @a s
18845
@return a JSON pointer object
18846
18847
@since version 2.0.0
18848
*/
18849
inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
18850
0
{
18851
0
    return nlohmann::json::json_pointer(std::string(s, n));
18852
0
}
18853
18854
// #include <nlohmann/detail/macro_unscope.hpp>
18855
18856
18857
// restore GCC/clang diagnostic settings
18858
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
18859
    #pragma GCC diagnostic pop
18860
#endif
18861
#if defined(__clang__)
18862
    #pragma GCC diagnostic pop
18863
#endif
18864
18865
// clean up
18866
#undef JSON_INTERNAL_CATCH
18867
#undef JSON_CATCH
18868
#undef JSON_THROW
18869
#undef JSON_TRY
18870
#undef JSON_LIKELY
18871
#undef JSON_UNLIKELY
18872
#undef JSON_DEPRECATED
18873
#undef JSON_HAS_CPP_14
18874
#undef JSON_HAS_CPP_17
18875
#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
18876
#undef NLOHMANN_BASIC_JSON_TPL
18877
18878
18879
#endif
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/libs/useful/useful.h
Line
Count
Source
1
#ifndef Iusefull_H
2
#define Iusefull_H
3
4
#include <iostream>
5
#include <string>
6
#include <vector>
7
#include <ostream>
8
#include <chrono>
9
#include <sstream>
10
#include <stdio.h>
11
#include <stdlib.h>
12
#include <iomanip>
13
#ifndef ANDROID
14
#include "json.hpp"
15
#endif
16
17
std::vector<std::string> split_string(const std::string& s, char separator );
18
19
class useful_F_libs {
20
public:
21
    static  void write_to_mkfifo(const std::string& path, const std::string &msg);
22
    static  std::string read_from_mkfifo(const std::string &path);
23
    static size_t  WriteCallback(void *contents, size_t size, size_t nmemb, void *userp);
24
    static std::string find_tag (const std::string &temp);
25
    //////////////////// HTTP req //////////////////////////
26
    static std::string httpPost(const std::string &url, int timeoutSeconds);
27
    static std::string httpPost(const std::string &url);
28
    static void downloadFile(const std::string &url, const std::string &path, int timeoutSeconds);
29
    static std::string replaceAll(std::string str, const std::string& from, const std::string& to);
30
    static std::string removeHtmlTag(std::string &data);
31
    /////////////////////  JSON ////////////////////////////
32
33
#ifndef ANDROID
34
    static nlohmann::json getJson(const std::string &url);
35
#endif
36
};
37
namespace std
38
{
39
40
#ifdef ANDROID
41
template <typename T>
42
int stoi(T s){
43
    return atoi(s.c_str());
44
}
45
#endif
46
47
template <typename T>
48
std::string to_string(T value)
49
{
50
    std::ostringstream os;
51
    os << value;
52
    return os.str();
53
}
54
} // namespace std
55
56
template <typename T>
57
std::string to_string_with_precision(const T a_value, const int n = 4)
58
59
{
59
59
    std::ostringstream out;
60
59
    out << std::setprecision(n) << a_value;
61
59
    return out.str();
62
59
}
63
64
struct Clock{
65
private:
66
    std::time_t m_time;
67
#ifdef BT_TEST
68
    static unsigned int m_BT_H;
69
    static unsigned int m_BT_M;
70
#endif
71
public:
72
    unsigned int m_h = 0;
73
    unsigned int m_min = 0;
74
985
    Clock () {}
75
37
    Clock(std::string t){
76
37
        std::vector<std::string> vt = split_string(t,':');
77
37
        int h = std::stoi(vt.at(0));
78
37
        int m = std::stoi(vt.at(1));
79
37
        set(static_cast <unsigned int>(h),static_cast <unsigned int>(m));
80
37
    }
81
82
702
    Clock(unsigned int h, unsigned int m) {
83
702
        set(h,m);
84
702
    }
85
    /////////////////////////////////////////////////////////////////////////////////////
86
741
    void set(unsigned int h, unsigned int m){
87
741
        if (h<24 && m <60){
88
740
            this->m_h = h;
89
740
            this->m_min = m;
90
740
        }
91
741
        else {
92
1
            throw 0;
93
1
        }
94
741
    }
95
96
    /////////////////////////////////////////////////////////////////////////////////////
97
81
    const std::string getString(){
98
81
        std::stringstream ret;
99
81
        if (m_h < 10) {
100
66
            ret << "0";
101
66
        }
102
81
        ret << m_h;
103
81
        ret << ":";
104
81
        if (m_min < 10) {
105
58
            ret << "0";
106
58
        }
107
81
        ret << m_min;
108
81
        return ret.str();
109
81
    }
110
    /////////////////////////////////////////////////////////////////////////////////////
111
13
    bool operator == (const Clock & c){
112
13
        if ((this->m_h == c.m_h) && (this->m_min == c.m_min)){
113
11
            return true;
114
11
        }
115
13
        else{
116
2
            return false;
117
2
        }
118
13
    }
119
    /////////////////////////////////////////////////////////////////////////////////////
120
13
    bool operator != (const Clock & c){
121
13
        if ((this->m_h != c.m_h) || (this->m_min != c.m_min)){
122
8
            return true;
123
8
        }
124
13
        else{
125
5
            return false;
126
5
        }
127
13
    }
128
    /////////////////////////////////////////////////////////////////////////////////////
129
1
    friend std::ostream & operator<< (std::ostream &w ,  Clock &c) {
130
1
        return w << c.getString();
131
1
    }
132
    /////////////////////////////////////////////////////////////////////////////////////
133
18
    bool operator < (const Clock& c){
134
18
        if (this->m_h < c.m_h){
135
15
            return true;
136
15
        }
137
18
        else{
138
3
            if (this->m_h == c.m_h && this->m_min < c.m_min){
139
1
                return true;
140
1
            }
141
3
        }
142
18
        return false;
143
18
    }
144
    /////////////////////////////////////////////////////////////////////////////////////
145
4
    bool operator > (const Clock& c){
146
4
        if (this->m_h > c.m_h){
147
1
            return true;
148
1
        }
149
4
        else{
150
3
            if (this->m_h == c.m_h && this->m_min > c.m_min){
151
1
                return true;
152
1
            }
153
3
        }
154
4
        return false;
155
4
    }
156
    /////////////////////////////////////////////////////////////////////////////////////
157
5
    bool operator >= (const Clock& c){
158
5
        if (this->m_h > c.m_h){
159
2
            return true;
160
2
        }
161
5
        else if (this->m_h == c.m_h){
162
1
163
1
            if (this->m_min >= c.m_min){
164
1
                return true;
165
1
            }
166
1
        }
167
5
        return false;
168
5
    }
169
    /////////////////////////////////////////////////////////////////////////////////////
170
7
    bool operator <= (const Clock& c){
171
7
        if (this->m_h < c.m_h){
172
2
            return true;
173
2
        }
174
7
        else if (this->m_h == c.m_h){
175
2
176
2
            if (this->m_min <= c.m_min){
177
1
                return true;
178
1
            }
179
2
        }
180
7
        return false;
181
7
    }
182
    /////////////////////////////////////////////////////////////////////////////////////
183
193
    Clock  operator + (const Clock& c){
184
193
        unsigned int minutes, hours;
185
193
        minutes = m_min+ c.m_min;
186
193
        hours = m_h + c.m_h;
187
193
        if (minutes >59){
188
144
            minutes =  minutes % 60;
189
144
            hours+=1;
190
144
        }
191
193
        if (hours >= 24){
192
144
            hours-=24;
193
144
        }
194
193
        return  Clock(hours, minutes);
195
193
196
193
    }
197
    /////////////////////////////////////////////////////////////////////////////////////
198
5
    Clock&  operator += (const Clock& c){
199
5
        unsigned int minutes, hours;
200
5
        minutes = m_min+ c.m_min;
201
5
        hours = m_h + c.m_h;
202
5
        if (minutes >59){
203
4
            minutes =  minutes % 60;
204
4
            hours+=1;
205
4
        }
206
5
        if (hours >= 24){
207
4
            hours-=24;
208
4
        }
209
5
        this->m_h = hours;
210
5
        this->m_min = minutes;
211
5
        return *this;
212
5
213
5
    }
214
    /////////////////////////////////////////////////////////////////////////////////////
215
216
5
    unsigned int toSeconds(){
217
5
        return toSeconds(Clock(this->m_h, this->m_min) );
218
5
    }
219
    /////////////////////////////////////////////////////////////////////////////////////
220
221
6
    static unsigned int toSeconds(Clock t){
222
6
        return ((t.m_h*60) + t.m_min)*60;
223
6
    }
224
    /////////////////////////////////////////////////////////////////////////////////////
225
226
3
    static Clock fromSeconds(unsigned int sec){
227
3
        unsigned int h = sec/3600;
228
3
        unsigned int min = sec%3600;
229
3
        min = min/60;
230
3
        return Clock(h,min);
231
3
    }
232
    /////////////////////////////////////////////////////////////////////////////////////
233
234
    static Clock periodOfTime(Clock start, Clock end)
235
2
    {
236
2
        if (end >= start){
237
1
            return Clock::fromSeconds(end.toSeconds() - start.toSeconds()  );
238
1
        }
239
2
        else{
240
1
            return Clock::fromSeconds(end.toSeconds() + ( Clock::toSeconds(Clock(23,59))+ 60 - start.toSeconds() ) );
241
1
        }
242
2
        //return diff;
243
2
    }
244
    ////////////////////////////////////////////////////////////////////////////////////
245
    static unsigned int getUnixTime()
246
    {
247
        return static_cast<unsigned int> (std::time(nullptr));
248
    }
249
    /////////////////////////////////////////////////////////////////////////////////////
250
#ifdef BT_TEST
251
    static void setTime_forBT_usage(int h, int m)
252
    {
253
        m_BT_H = h;
254
        m_BT_M = m;
255
    }
256
#endif
257
    /////////////////////////////////////////////////////////////////////////////////////
258
    static Clock getTime()
259
245
    {
260
245
#ifdef BT_TEST
261
245
        return Clock(m_BT_H,m_BT_M);
262
#else
263
        time_t now = time(0);
264
        tm *ltm = localtime(&now);
265
        return Clock( static_cast <unsigned int>(ltm->tm_hour),static_cast <unsigned int>(ltm->tm_min) );
266
#endif
267
245
    }
268
    /////////////////////////////////////////////////////////////////////////////////////
269
    void stopwatchStart()
270
1
    {
271
1
        m_time = std::time(nullptr);
272
1
    }
273
    /////////////////////////////////////////////////////////////////////////////////////
274
    unsigned int  stopwatchStopAndGetResult()
275
1
    {
276
1
        return static_cast<unsigned int>(std::time(nullptr) - m_time);
277
1
    }
278
};
279
280
enum class STATE {
281
    OFF,
282
    ON,
283
    UNKNOWN,
284
    PLAY,
285
    PAUSE,
286
    STOP,
287
    ACTIVE,
288
    DEACTIVE,
289
    WORKING,
290
    DEFINE,
291
    UNDEFINE,
292
    LOCK,
293
    UNLOCK,
294
    EMPTY,
295
    FULL,
296
    SEND_OK,
297
    SEND_NOK
298
    //WARNING remember add new state to stateToString() usefull.cpp
299
};
300
301
302
std::string stateToString(STATE s);
303
STATE stringToState(const std::string& s);
304
305
#endif
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/libs/sunrise-sunset/sunriseset.cpp
Line
Count
Source (jump to first uncovered line)
1
#include "sunriseset.h"
2
3
double SunRiseSet::FNday(int y, int m, int d, float h)
4
44
{
5
44
    long int luku = - 7 * (y + (m + 9)/12)/4 + 275*m/9 + d;
6
44
7
44
    // Typecasting needed for TClite on PC DOS at least, to avoid product overflow
8
44
    luku+= (long int)y*367;
9
44
10
44
    return (double)luku - 730531.5 + h/24.0;
11
44
}
12
double SunRiseSet::FNrange(double x)
13
132
{
14
132
    double b = x / tpi;
15
132
    double a = tpi * (b - (long)(b));
16
132
    if (a < 0) a = tpi + a;
17
132
    return a;
18
132
}
19
20
double SunRiseSet::f0(double lat, double declin)
21
44
{
22
44
    double fo,dfo;
23
44
    // Correction: different sign at S HS
24
44
    dfo = rads*(0.5*SunDia + AirRefr); if (lat < 0.0) dfo = -dfo;
25
44
    fo = tan(declin + dfo) * tan(lat*rads);
26
44
27
44
    if (fo > 0.99999) fo=1.0; // to avoid overflow //
28
44
    fo = asin(fo) + pi/2.0;
29
44
    return fo;
30
44
}
31
32
double SunRiseSet::f1(double lat, double declin)
33
1
{
34
1
    double fi,df1;
35
1
    // Correction: different sign at S HS
36
1
    df1 = rads * 6.0; if (lat < 0.0) df1 = -df1;
37
1
    fi = tan(declin + df1) * tan(lat*rads);
38
1
39
1
    if (fi > 0.99999) fi=1.0; // to avoid overflow //
40
1
    fi = asin(fi) + pi/2.0;
41
1
    return fi;
42
1
}
43
44
double SunRiseSet::FNsun(double d)
45
44
{
46
44
    // mean longitude of the Sun
47
44
    L = FNrange(280.461 * rads + .9856474 * rads * d);
48
44
49
44
    // mean anomaly of the Sun
50
44
    g = FNrange(357.528 * rads + .9856003 * rads * d);
51
44
52
44
    // Ecliptic longitude of the Sun
53
44
    return FNrange(L + 1.915 * rads * sin(g) + .02 * rads * sin(2 * g));
54
44
}
55
56
Clock SunRiseSet::gethrmn(double dhr)
57
53
{
58
53
59
53
    int hr,mn;
60
53
61
53
    hr=(int) dhr;
62
53
    mn = (dhr - (double) hr)*60;
63
53
64
53
    Clock ret(hr,mn);
65
53
66
53
    return ret;
67
53
}
68
69
SunRiseSet::SunRiseSet()
70
195
{
71
195
72
195
}
73
74
std::string SunRiseSet::getAllData()
75
1
{
76
1
    double y,m,day,h,latit,longit;
77
1
78
1
    time_t sekunnit;
79
1
    struct tm *p;
80
1
81
1
    // get the date and time from the user
82
1
    // read system date and extract the year
83
1
84
1
    /** First get current time **/
85
1
    time(&sekunnit);
86
1
87
1
    /** Next get localtime **/
88
1
89
1
    p=localtime(&sekunnit);
90
1
    // this is Y2K compliant algorithm
91
1
    y = 1900 + p->tm_year;
92
1
93
1
    m = p->tm_mon + 1;
94
1
    day = p->tm_mday;
95
1
    h = 12;
96
1
97
1
    std::cout << "Input latitude, longitude and timezone\n";
98
1
    latit = LATITUDE;
99
1
    longit = LONGITUDE;
100
1
    // Timezone hours
101
1
    double tzone= TIMEZONE;
102
1
    double d = FNday(y, m, day, h);
103
1
104
1
    // Use FNsun to find the ecliptic longitude of the
105
1
    // Sun
106
1
    double lambda = FNsun(d);
107
1
108
1
    // Obliquity of the ecliptic
109
1
    double obliq = 23.439 * rads - .0000004 * rads * d;
110
1
111
1
    // Find the RA and DEC of the Sun
112
1
    double alpha = atan2(cos(obliq) * sin(lambda), cos(lambda));
113
1
    double delta = asin(sin(obliq) * sin(lambda));
114
1
115
1
    // Find the Equation of Time in minutes
116
1
    // Correction suggested by David Smith
117
1
    double LL = L - alpha;
118
1
    if (L < pi) LL += tpi;
119
1
    double equation = 1440.0 * (1.0 - LL / tpi);
120
1
    double ha = f0(latit,delta);
121
1
    double hb = f1(latit,delta);
122
1
    double twx = hb - ha;   // length of twilight in radians
123
1
    twx = 12.0*twx/pi;      // length of twilight in degrees
124
1
125
1
    // Conversion of angle to hours and minutes //
126
1
    daylen = degs * ha / 7.5;
127
1
    if (daylen<0.0001) {daylen = 0.0;}
128
1
    // arctic winter   //
129
1
130
1
    double riset = 12.0 - 12.0 * ha/pi + tzone - longit/15.0 + equation/60.0;
131
1
    double settm = 12.0 + 12.0 * ha/pi + tzone - longit/15.0 + equation/60.0;
132
1
    //double noont = riset + 12.0 * ha/pi;
133
1
    //double altmax = 90.0 + delta * degs - latit;
134
1
    // Correction suggested by David Smith
135
1
    // to express as degrees from the N horizon
136
1
137
1
    //if (delta * degs > latit ) altmax = 90.0 + latit - delta * degs;
138
1
139
1
    double twam = riset - twx;    // morning twilight begin
140
1
    double twpm = settm + twx;      // evening twilight end
141
1
142
1
    if (riset > 24.0) riset-= 24.0;
143
1
    if (settm > 24.0) settm-= 24.0;
144
1
145
1
    std::stringstream ss;
146
1
    ss << "\n Sunrise and set\n";
147
1
    ss << "===============\n";
148
1
    ss << "  year  : " << y << '\n';
149
1
    ss << "  month : " << m << '\n';
150
1
    ss << "  day   : " << day << "\n\n";
151
1
    ss << "Days until Y2K :  " << d << '\n';
152
1
    ss << "Latitude :  " << latit << ", longitude:  " << longit << '\n';
153
1
    ss << "Timezone :  " << tzone << "\n\n";
154
1
    ss << "Declination : " << delta * degs << '\n';
155
1
    ss << "Daylength   : "<< gethrmn(daylen).m_h<<":"<<gethrmn(daylen).m_min<< " hours \n";
156
1
    ss << "Begin civil twilight: "<<
157
1
                 gethrmn(twam).m_h<<":"<<gethrmn(twam).m_min; std::cout << '\n';
158
1
159
1
    ss << "Sunrise     : "<< gethrmn(riset).m_h<<":"<<gethrmn(riset).m_min; std::cout << '\n';
160
1
    ss << "Sun altitude at noontime ";
161
1
162
1
163
1
    ss << "Sunset      : "<<
164
1
                 gethrmn(settm).m_h<<":"<<gethrmn(settm).m_min; std::cout << '\n';
165
1
    ss << "Civil twilight: "<<
166
1
                 gethrmn(twpm).m_h<<":"<<gethrmn(twpm).m_min; std::cout << '\n';
167
1
    return ss.str();
168
1
}
169
170
void SunRiseSet::setPosition(double LATITUDE, double LONGITUDE, int TIMEZONE)
171
0
{
172
0
    this->LATITUDE = LATITUDE;
173
0
    this->LONGITUDE = LONGITUDE;
174
0
    this->TIMEZONE = TIMEZONE;
175
0
}
176
177
Clock SunRiseSet::getSunRise()
178
25
{
179
25
    double y,m,day,h,latit,longit;
180
25
    time_t sekunnit;
181
25
    struct tm *p;
182
25
    // get the date and time from the user
183
25
    // read system date and extract the year
184
25
185
25
    /** First get current time **/
186
25
    time(&sekunnit);
187
25
188
25
    /** Next get localtime **/
189
25
    p=localtime(&sekunnit);
190
25
    // this is Y2K compliant algorithm
191
25
    y = 1900 + p->tm_year;
192
25
    m = p->tm_mon + 1;
193
25
    day = p->tm_mday;
194
25
    h = 12;
195
25
    latit = LATITUDE;
196
25
    longit = LONGITUDE;
197
25
    // Timezone hours
198
25
    double tzone = TIMEZONE;
199
25
    double d = FNday(y, m, day, h);
200
25
    // Use FNsun to find the ecliptic longitude of the
201
25
    // Sun
202
25
    double lambda = FNsun(d);
203
25
    // Obliquity of the ecliptic
204
25
    double obliq = 23.439 * rads - .0000004 * rads * d;
205
25
    // Find the RA and DEC of the Sun
206
25
    double alpha = atan2(cos(obliq) * sin(lambda), cos(lambda));
207
25
    double delta = asin(sin(obliq) * sin(lambda));
208
25
    double LL = L - alpha;
209
25
    if (L < pi) LL += tpi;
210
25
    double equation = 1440.0 * (1.0 - LL / tpi);
211
25
    double ha = f0(latit,delta);
212
25
    // Conversion of angle to hours and minutes //
213
25
    daylen = degs * ha / 7.5;
214
25
    if (daylen<0.0001) {daylen = 0.0;}
215
25
    // arctic winter   //
216
25
    double riset = 12.0 - 12.0 * ha/pi + tzone - longit/15.0 + equation/60.0;
217
25
218
25
    if (riset > 24.0) riset-= 24.0;
219
25
    return  gethrmn(riset);
220
25
}
221
222
Clock SunRiseSet::getDayLength()
223
7
{
224
7
    double y,m,day,h,latit;
225
7
    time_t sekunnit;
226
7
    struct tm *p;
227
7
228
7
    // get the date and time from the user
229
7
    // read system date and extract the year
230
7
231
7
    /** First get current time **/
232
7
    time(&sekunnit);
233
7
234
7
    /** Next get localtime **/
235
7
    p=localtime(&sekunnit);
236
7
    // this is Y2K compliant algorithm
237
7
    y = 1900 + p->tm_year;
238
7
    m = p->tm_mon + 1;
239
7
    day = p->tm_mday;
240
7
    h = 12;
241
7
    latit = LATITUDE;
242
7
    double d = FNday(y, m, day, h);
243
7
244
7
    // Use FNsun to find the ecliptic longitude of the
245
7
    // Sun
246
7
    double lambda = FNsun(d);
247
7
    // Obliquity of the ecliptic
248
7
    double obliq = 23.439 * rads - .0000004 * rads * d;
249
7
    double delta = asin(sin(obliq) * sin(lambda));
250
7
    // Find the Equation of Time in minutes
251
7
    // Correction suggested by David Smith
252
7
    double ha = f0(latit,delta);
253
7
    // Conversion of angle to hours and minutes //
254
7
    daylen = degs * ha / 7.5;
255
7
    if (daylen<0.0001) {daylen = 0.0;}
256
7
    // arctic winter   //
257
7
258
7
    return  gethrmn(daylen);
259
7
}
260
261
Clock SunRiseSet::getSunSet()
262
11
{
263
11
    double y,m,day,h,latit,longit;
264
11
265
11
    time_t sekunnit;
266
11
    struct tm *p;
267
11
268
11
    // get the date and time from the user
269
11
    // read system date and extract the year
270
11
271
11
    /** First get current time **/
272
11
    time(&sekunnit);
273
11
274
11
    /** Next get localtime **/
275
11
276
11
    p=localtime(&sekunnit);
277
11
    // this is Y2K compliant algorithm
278
11
    y = 1900 + p->tm_year;
279
11
280
11
    m = p->tm_mon + 1;
281
11
    day = p->tm_mday;
282
11
    h = 12;
283
11
284
11
    latit = LATITUDE;
285
11
    longit = LONGITUDE;
286
11
    // Timezone hours
287
11
    double tzone = TIMEZONE;
288
11
289
11
    double d = FNday(y, m, day, h);
290
11
291
11
    // Use FNsun to find the ecliptic longitude of the
292
11
    // Sun
293
11
294
11
    double lambda = FNsun(d);
295
11
296
11
    // Obliquity of the ecliptic
297
11
298
11
    double obliq = 23.439 * rads - .0000004 * rads * d;
299
11
300
11
    // Find the RA and DEC of the Sun
301
11
302
11
    double alpha = atan2(cos(obliq) * sin(lambda), cos(lambda));
303
11
    double delta = asin(sin(obliq) * sin(lambda));
304
11
305
11
306
11
    // Find the Equation of Time in minutes
307
11
    // Correction suggested by David Smith
308
11
309
11
    double LL = L - alpha;
310
11
    if (L < pi) LL += tpi;
311
11
    double equation = 1440.0 * (1.0 - LL / tpi);
312
11
313
11
314
11
    double ha = f0(latit,delta);
315
11
316
11
    // Conversion of angle to hours and minutes //
317
11
    daylen = degs * ha / 7.5;
318
11
    if (daylen<0.0001) {daylen = 0.0;}
319
11
    // arctic winter   //
320
11
321
11
    //double riset = 12.0 - 12.0 * ha/pi + tzone - longit/15.0 + equation/60.0;
322
11
    double settm = 12.0 + 12.0 * ha/pi + tzone - longit/15.0 + equation/60.0;
323
11
324
11
    //if (riset > 24.0) riset-= 24.0;
325
11
    if (settm > 24.0) settm-= 24.0;
326
11
    return  gethrmn(settm);
327
11
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/libs/useful/test/useful_bt.cpp
Line
Count
Source
1
#include <gtest/gtest.h>
2
#include <gmock/gmock.h>
3
#include <sys/types.h>
4
#include <sys/stat.h>
5
#include <stdio.h>
6
#include <string.h>
7
#include <fcntl.h>
8
#include <unistd.h>
9
#include "../useful.h"
10
///////////////////////////////////////////////////// TEST ///////////////////////////////////////////////////////\
11
12
TEST(ClockClass, AddTwoHours)
13
1
{
14
1
    Clock f(13,57);
15
1
    Clock g(23,59);
16
1
    Clock r = f+g;
17
1
    EXPECT_EQ(r.getString(), "13:56");
18
1
}
19
20
TEST(ClockClass, lessThen_Hours)
21
1
{
22
1
    Clock f(13,57);
23
1
    Clock g(23,59);
24
1
    EXPECT_EQ(f<g, true);
25
1
}
26
27
TEST(ClockClass, plus_operator)
28
1
{
29
1
    Clock f(13,57);
30
1
    f+=Clock("04:04");
31
1
    EXPECT_EQ(f.getString(),"18:01");
32
1
}
33
34
TEST(ClockClass, _operator)
35
1
{
36
1
    EXPECT_FALSE(Clock("04:04") == Clock("04:05"));
37
1
    EXPECT_FALSE(Clock("05:05") == Clock("04:05"));
38
1
    EXPECT_TRUE(Clock("05:05") == Clock("05:05"));
39
1
    EXPECT_FALSE(Clock("05:05") != Clock("05:05"));
40
1
    EXPECT_TRUE(Clock("04:05") != Clock("05:05"));
41
1
    EXPECT_TRUE(Clock("04:05") != Clock("04:04"));
42
1
    EXPECT_TRUE(Clock("04:05") > Clock("04:04"));
43
1
    EXPECT_FALSE(Clock("03:05") > Clock("04:04"));
44
1
    EXPECT_TRUE(Clock("04:05") >= Clock("04:04"));
45
1
    EXPECT_FALSE(Clock("04:05") <= Clock("04:04"));
46
1
    EXPECT_FALSE(Clock("05:05") <= Clock("04:05"));
47
1
    EXPECT_TRUE(Clock("03:05") <= Clock("04:05"));
48
1
    EXPECT_TRUE(Clock("04:05") <= Clock("04:06"));
49
1
    EXPECT_FALSE(Clock("05:05") < Clock("04:06"));
50
1
    EXPECT_TRUE(Clock("04:05") < Clock("04:06"));
51
1
    EXPECT_TRUE(Clock("08:05") > Clock("04:06"));
52
1
53
1
    std::stringstream s;
54
1
    Clock f("00:00");
55
1
    s << f;
56
1
    EXPECT_STREQ("00:00", s.str().c_str());
57
1
58
1
    Clock g("20:00");
59
1
    f = g.getTime();
60
1
    g += Clock("23:43");
61
1
    EXPECT_STREQ("19:43", g.getString().c_str());
62
1
}
63
64
TEST(ClockClass, periodOfTime)
65
1
{
66
1
    Clock f(13,57);
67
1
    Clock g(22,22);
68
1
    Clock r = Clock::periodOfTime(f,g);
69
1
    EXPECT_EQ(r.getString(),"08:25");
70
1
    r = Clock::periodOfTime(g,f);
71
1
    EXPECT_EQ(r.getString(),"15:35");
72
1
}
73
74
TEST(ClockClass, from_to_second)
75
1
{
76
1
    Clock f;
77
1
    f.set(13,57);
78
1
    unsigned int sec = f.toSeconds();
79
1
    Clock g = Clock::fromSeconds(sec);
80
1
    EXPECT_EQ(f.getString(),g.getString());
81
1
}
82
83
TEST(ClockClass, stopwatch)
84
1
{
85
1
    Clock f;
86
1
    f.stopwatchStart();
87
1
    sleep(1);
88
1
    EXPECT_EQ(1,f.stopwatchStopAndGetResult());
89
1
}
90
91
TEST(ClockClass, wrongSet)
92
1
{
93
1
    Clock f;
94
1
    EXPECT_ANY_THROW(f.set(99,99));
95
1
}
96
97
TEST(ClockClass, to_string_with_precision_TC)
98
1
{
99
1
    double d = 1.0/3.0;
100
1
    EXPECT_STREQ("0.33", to_string_with_precision(d,2).c_str() );
101
1
}
102
103
TEST(JSON, getJSON)
104
1
{
105
1
    nlohmann::json test_JSON = useful_F_libs::getJson("http://cyniu88.no-ip.pl/test/json/on_lightning.json");
106
1
    auto testKey = test_JSON["success"].get<bool>();
107
1
108
1
    std::cout << " JSON JEST" << std::endl << test_JSON.dump(4) << std::endl;
109
1
110
    EXPECT_TRUE(testKey);
111
}
112
113
//TEST(mkfifo_test, mkfifoFile)
114
//{
115
//    std::string path = "/mnt/ramdisk/FifoFile";
116
//    std::string msg = "p";
117
//    std::string returnString = "NULL";
118
//    int temp = mkfifo(path.c_str(),0666);
119
120
//    if ( temp == -1)
121
//        std::cout << "plik istnieje "<<strerror(errno)<< std::endl;
122
//    else if (temp == 0)
123
//        std::cout << "plik stworzony"<< std::endl;
124
//    else
125
//        FAIL();
126
127
//    useful_F_libs::write_to_mkfifo(path,msg);
128
//}
129
130
//TEST(mkfifo_test, mkfifoFile2)
131
//{
132
//    std::string msg = "p";
133
//    std::string path = "/mnt/ramdisk/FifoFile";
134
//    std::string returnString = useful_F_libs::read_from_mkfifo(path);
135
//    //unlink(path.c_str());
136
137
//    EXPECT_STREQ(returnString.c_str(), msg.c_str()) << "odczytano smieci";
138
//    //TODO not
139
140
//}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/libs/useful/test/useful_bt.cpp
Line
Count
Source
1
#include <gtest/gtest.h>
2
#include <gmock/gmock.h>
3
#include <sys/types.h>
4
#include <sys/stat.h>
5
#include <stdio.h>
6
#include <string.h>
7
#include <fcntl.h>
8
#include <unistd.h>
9
#include "../useful.h"
10
///////////////////////////////////////////////////// TEST ///////////////////////////////////////////////////////\
11
12
TEST(ClockClass, AddTwoHours)
13
1
{
14
1
    Clock f(13,57);
15
1
    Clock g(23,59);
16
1
    Clock r = f+g;
17
1
    EXPECT_EQ(r.getString(), "13:56");
18
1
}
19
20
TEST(ClockClass, lessThen_Hours)
21
1
{
22
1
    Clock f(13,57);
23
1
    Clock g(23,59);
24
1
    EXPECT_EQ(f<g, true);
25
1
}
26
27
TEST(ClockClass, plus_operator)
28
1
{
29
1
    Clock f(13,57);
30
1
    f+=Clock("04:04");
31
1
    EXPECT_EQ(f.getString(),"18:01");
32
1
}
33
34
TEST(ClockClass, _operator)
35
1
{
36
1
    EXPECT_FALSE(Clock("04:04") == Clock("04:05"));
37
1
    EXPECT_FALSE(Clock("05:05") == Clock("04:05"));
38
1
    EXPECT_TRUE(Clock("05:05") == Clock("05:05"));
39
1
    EXPECT_FALSE(Clock("05:05") != Clock("05:05"));
40
1
    EXPECT_TRUE(Clock("04:05") != Clock("05:05"));
41
1
    EXPECT_TRUE(Clock("04:05") != Clock("04:04"));
42
1
    EXPECT_TRUE(Clock("04:05") > Clock("04:04"));
43
1
    EXPECT_FALSE(Clock("03:05") > Clock("04:04"));
44
1
    EXPECT_TRUE(Clock("04:05") >= Clock("04:04"));
45
1
    EXPECT_FALSE(Clock("04:05") <= Clock("04:04"));
46
1
    EXPECT_FALSE(Clock("05:05") <= Clock("04:05"));
47
1
    EXPECT_TRUE(Clock("03:05") <= Clock("04:05"));
48
1
    EXPECT_TRUE(Clock("04:05") <= Clock("04:06"));
49
1
    EXPECT_FALSE(Clock("05:05") < Clock("04:06"));
50
1
    EXPECT_TRUE(Clock("04:05") < Clock("04:06"));
51
1
    EXPECT_TRUE(Clock("08:05") > Clock("04:06"));
52
1
53
1
    std::stringstream s;
54
1
    Clock f("00:00");
55
1
    s << f;
56
1
    EXPECT_STREQ("00:00", s.str().c_str());
57
1
58
1
    Clock g("20:00");
59
1
    f = g.getTime();
60
1
    g += Clock("23:43");
61
1
    EXPECT_STREQ("19:43", g.getString().c_str());
62
1
}
63
64
TEST(ClockClass, periodOfTime)
65
1
{
66
1
    Clock f(13,57);
67
1
    Clock g(22,22);
68
1
    Clock r = Clock::periodOfTime(f,g);
69
1
    EXPECT_EQ(r.getString(),"08:25");
70
1
    r = Clock::periodOfTime(g,f);
71
1
    EXPECT_EQ(r.getString(),"15:35");
72
1
}
73
74
TEST(ClockClass, from_to_second)
75
1
{
76
1
    Clock f;
77
1
    f.set(13,57);
78
1
    unsigned int sec = f.toSeconds();
79
1
    Clock g = Clock::fromSeconds(sec);
80
1
    EXPECT_EQ(f.getString(),g.getString());
81
1
}
82
83
TEST(ClockClass, stopwatch)
84
1
{
85
1
    Clock f;
86
1
    f.stopwatchStart();
87
1
    sleep(1);
88
1
    EXPECT_EQ(1,f.stopwatchStopAndGetResult());
89
1
}
90
91
TEST(ClockClass, wrongSet)
92
1
{
93
1
    Clock f;
94
1
    EXPECT_ANY_THROW(f.set(99,99));
95
1
}
96
97
TEST(ClockClass, to_string_with_precision_TC)
98
1
{
99
1
    double d = 1.0/3.0;
100
1
    EXPECT_STREQ("0.33", to_string_with_precision(d,2).c_str() );
101
1
}
102
103
TEST(JSON, getJSON)
104
1
{
105
1
    nlohmann::json test_JSON = useful_F_libs::getJson("http://cyniu88.no-ip.pl/test/json/on_lightning.json");
106
1
    auto testKey = test_JSON["success"].get<bool>();
107
1
108
1
    std::cout << " JSON JEST" << std::endl << test_JSON.dump(4) << std::endl;
109
1
110
1
    EXPECT_TRUE(testKey);
111
1
}
112
113
//TEST(mkfifo_test, mkfifoFile)
114
//{
115
//    std::string path = "/mnt/ramdisk/FifoFile";
116
//    std::string msg = "p";
117
//    std::string returnString = "NULL";
118
//    int temp = mkfifo(path.c_str(),0666);
119
120
//    if ( temp == -1)
121
//        std::cout << "plik istnieje "<<strerror(errno)<< std::endl;
122
//    else if (temp == 0)
123
//        std::cout << "plik stworzony"<< std::endl;
124
//    else
125
//        FAIL();
126
127
//    useful_F_libs::write_to_mkfifo(path,msg);
128
//}
129
130
//TEST(mkfifo_test, mkfifoFile2)
131
//{
132
//    std::string msg = "p";
133
//    std::string path = "/mnt/ramdisk/FifoFile";
134
//    std::string returnString = useful_F_libs::read_from_mkfifo(path);
135
//    //unlink(path.c_str());
136
137
//    EXPECT_STREQ(returnString.c_str(), msg.c_str()) << "odczytano smieci";
138
//    //TODO not
139
140
//}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/libs/useful/usefull.cpp
Line
Count
Source (jump to first uncovered line)
1
#include "useful.h"
2
#include <sys/fcntl.h>
3
#include <unistd.h>
4
#include <sys/types.h>
5
#include <sys/stat.h>
6
#include <fcntl.h>
7
#include <fstream>
8
9
#ifndef IDOM
10
#include <curl/curl.h>
11
#endif
12
37
std::vector<std::string> split_string(const std::string& s, char separator ){
13
37
    std::vector<std::string> output;
14
37
    std::string::size_type prev_pos = 0, pos = 0;
15
37
16
74
    while((pos = s.find(separator, pos)) != std::string::npos)
17
37
    {
18
37
        std::string substring( s.substr(prev_pos, pos-prev_pos) );
19
37
        output.push_back(substring);
20
37
        prev_pos = ++pos;
21
37
    }
22
37
    try {
23
37
        output.push_back(s.substr(prev_pos, pos-prev_pos)); // Last word
24
37
    }
25
37
    catch (...){
26
0
27
0
    }
28
37
    return output;
29
37
}
30
31
662
std::string stateToString(STATE s){
32
662
    switch (s) {
33
43
    case STATE::OFF:        return "OFF";
34
43
    case STATE::ON:         return "ON";
35
43
    case STATE::PLAY:       return "PLAY";
36
43
    case STATE::PAUSE:      return "PAUSE";
37
43
    case STATE::STOP:       return "STOP";
38
43
    case STATE::ACTIVE:     return "ACTIVE";
39
47
    case STATE::DEACTIVE:   return "DEACTIVE";
40
43
    case STATE::WORKING:    return "WORKING";
41
43
    case STATE::DEFINE:     return "DEFINE";
42
416
    case STATE::UNDEFINE:   return "UNDEFINE";
43
43
    case STATE::LOCK:       return "LOCK";
44
43
    case STATE::UNLOCK:     return "UNLOCK";
45
43
    case STATE::EMPTY:      return "EMPTY";
46
43
    case STATE::FULL:       return "FULL";
47
43
    case STATE::SEND_OK:    return "SEND_OK";
48
43
    case STATE::SEND_NOK:   return "SEND_NOK";
49
43
    default:
50
42
        return "UNKNOWN";
51
0
    }
52
662
}
53
54
1.94k
STATE stringToState(const std::string& s){
55
1.94k
    if(s == "OFF")
56
1.94k
        return STATE::OFF;
57
1.94k
    else if (s == "ON")
58
1.56k
        return STATE::ON;
59
1.56k
    else if (s == "PLAY")
60
1.17k
        return STATE::PLAY;
61
1.17k
    else if (s == "PAUSE")
62
1.17k
        return STATE::PAUSE;
63
1.17k
    else if (s == "STOP")
64
1.17k
        return STATE::STOP;
65
1.17k
    else if (s == "ACTIVE")
66
1.17k
        return STATE::ACTIVE;
67
1.17k
    else if (s == "DEACTIVE")
68
1.17k
        return STATE::DEACTIVE;
69
1.17k
    else if (s == "WORKING")
70
1.17k
        return STATE::WORKING;
71
1.17k
    else if (s == "DEFINE")
72
1.17k
        return STATE::DEFINE;
73
1.17k
    else if (s == "UNDEFINE")
74
1.17k
        return STATE::UNDEFINE;
75
1.17k
    else if (s == "LOCK")
76
1.17k
        return STATE::LOCK;
77
1.17k
    else if (s == "UNLOCK")
78
1.17k
        return STATE::UNLOCK;
79
1.17k
    else if (s == "EMPTY")
80
1.17k
        return STATE::EMPTY;
81
1.17k
    else if (s == "FULL")
82
1.17k
        return STATE::FULL;
83
1.17k
    else if (s == "SEND_OK")
84
1.17k
        return STATE::SEND_OK;
85
1.17k
    else if (s == "SEND_NOK")
86
1.17k
        return STATE::SEND_NOK;
87
1.17k
    else
88
1.17k
        return STATE::UNKNOWN;
89
1.94k
}
90
91
#ifndef IDOM
92
void useful_F_libs::write_to_mkfifo(const std::string &path, const std::string& msg)
93
6
{
94
6
    errno = 0;
95
6
    int fd = open(path.c_str(), O_RDWR| O_NONBLOCK );
96
6
    std::cout << "write open file: " << fd << " path " << path.c_str() << " msg: " << msg <<std::endl;
97
6
    std::cout << "write_to_mkfifo( error - " << strerror(  errno ) <<   std::endl;
98
6
    write(fd, msg.c_str(), msg.size());
99
6
    close(fd);
100
6
}
101
102
std::string useful_F_libs::read_from_mkfifo(const std::string& path)
103
11
{
104
11
    /* char buf[10];
105
11
    //open, read, and display the message from the FIFO
106
11
    int fd = open(path.c_str(), O_RDONLY | O_NONBLOCK);
107
11
    std::cout <<"read open file: " << fd <<std::endl;
108
11
    read(fd, buf, sizeof (buf));
109
11
    std::cout << "buf: " << buf << std::endl;
110
11
    close(fd);
111
11
    return (std::string(buf));
112
11
*/    std::string buf = "NULL";
113
11
    std::fstream fd;
114
11
    fd.open(path.c_str(), std::fstream::in | std::fstream::out | std::fstream::app);
115
11
116
11
    std::getline(fd,buf);
117
11
    return buf;
118
11
}
119
120
size_t useful_F_libs::WriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
121
23
{
122
23
    ((std::string*)userp)->append((char*)contents, size * nmemb);
123
23
    return size * nmemb;
124
23
}
125
126
std::string useful_F_libs::find_tag(const std::string& temp)
127
14
{
128
14
    std::string value = "";
129
294
    for (unsigned int i = 0; i<temp.size();++i){
130
294
131
294
        if (temp.at(i) =='>')
132
294
        {  int z = i+1;
133
42
            while (temp.at(z)!='<')
134
28
            {
135
28
                value+= temp.at(z);
136
28
                ++z;
137
28
            }
138
14
            break;
139
14
        }
140
294
    }
141
14
    return value;
142
14
}
143
144
#ifndef BT_TEST
145
std::string useful_F_libs::httpPost(const std::string& url, int timeoutSeconds)
146
{
147
    CURL *curl;
148
    CURLcode res;
149
    std::string readBuffer;
150
    curl = curl_easy_init();
151
152
    if(curl) {
153
        curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeoutSeconds);
154
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
155
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, useful_F_libs::WriteCallback);
156
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
157
        res = curl_easy_perform(curl);
158
        /* Check for errors */
159
        if(res != CURLE_OK)
160
            fprintf(stderr, "curl_easy_perform() failed: %s\n",
161
                    curl_easy_strerror(res));
162
163
        /* always cleanup */
164
        curl_easy_cleanup(curl);
165
    }
166
    curl_global_cleanup();
167
168
    return readBuffer;
169
}
170
171
std::string useful_F_libs::httpPost(const std::string& url)
172
{
173
    return useful_F_libs::httpPost(url, 10);
174
}
175
#endif
176
177
void useful_F_libs::downloadFile(const std::string& url, const std::string& path, int timeoutSeconds)
178
0
{
179
0
    CURL *curl;
180
0
    //CURLcode res;
181
0
182
0
    curl = curl_easy_init();
183
0
    if (curl) {
184
0
        FILE *fp = fopen(path.c_str(),"wb");
185
0
        curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeoutSeconds);
186
0
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
187
0
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NULL);
188
0
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
189
0
        //res = curl_easy_perform(curl);
190
0
        /* always cleanup */
191
0
        curl_easy_cleanup(curl);
192
0
        fclose(fp);
193
0
    }
194
0
}
195
196
3
std::string useful_F_libs::replaceAll(std::string str, const std::string& from, const std::string& to) {
197
3
    size_t start_pos = 0;
198
11
    while((start_pos = str.find(from, start_pos)) != std::string::npos) {
199
8
        str.replace(start_pos, from.length(), to);
200
8
        start_pos += to.length(); // Handles case where 'to' is a substring of 'from'
201
8
    }
202
3
    return str;
203
3
}
204
std::string useful_F_libs::removeHtmlTag(std::string &data)
205
2
{
206
2
    data = useful_F_libs::replaceAll(data,"</dl>","\n");
207
2
208
2
    //data = useful_F::replaceAll(data,"    "," ");
209
2
    bool copy = true;
210
2
    std::string plainString = "";
211
2
    std::stringstream convertStream;
212
2
213
2
    // remove all xml tags
214
2.88k
    for (unsigned int i=0; i < data.length(); i++)
215
2.87k
    {
216
2.87k
        convertStream << data[i];
217
2.87k
218
2.87k
        if(convertStream.str().compare("<") == 0) copy = false;
219
2.87k
        else if(convertStream.str().compare(">") == 0)
220
2.85k
        {
221
19
            copy = true;
222
19
            convertStream.str(std::string());
223
19
            continue;
224
19
        }
225
2.87k
226
2.87k
        if(copy) plainString.append(convertStream.str());
227
2.85k
228
2.85k
        convertStream.str(std::string());
229
2.85k
    }
230
2
231
2
    return plainString;
232
2
}
233
234
nlohmann::json useful_F_libs::getJson(const std::string& url)
235
4
{
236
4
    std::string str = useful_F_libs::httpPost(url);
237
4
    nlohmann::json jj = nlohmann::json::parse( str);
238
4
239
4
    return jj;
240
4
}
241
#endif
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/libs/useful/useful.h
Line
Count
Source
1
#ifndef Iusefull_H
2
#define Iusefull_H
3
4
#include <iostream>
5
#include <string>
6
#include <vector>
7
#include <ostream>
8
#include <chrono>
9
#include <sstream>
10
#include <stdio.h>
11
#include <stdlib.h>
12
#include <iomanip>
13
#ifndef ANDROID
14
#include "json.hpp"
15
#endif
16
17
std::vector<std::string> split_string(const std::string& s, char separator );
18
19
class useful_F_libs {
20
public:
21
    static  void write_to_mkfifo(const std::string& path, const std::string &msg);
22
    static  std::string read_from_mkfifo(const std::string &path);
23
    static size_t  WriteCallback(void *contents, size_t size, size_t nmemb, void *userp);
24
    static std::string find_tag (const std::string &temp);
25
    //////////////////// HTTP req //////////////////////////
26
    static std::string httpPost(const std::string &url, int timeoutSeconds);
27
    static std::string httpPost(const std::string &url);
28
    static void downloadFile(const std::string &url, const std::string &path, int timeoutSeconds);
29
    static std::string replaceAll(std::string str, const std::string& from, const std::string& to);
30
    static std::string removeHtmlTag(std::string &data);
31
    /////////////////////  JSON ////////////////////////////
32
33
#ifndef ANDROID
34
    static nlohmann::json getJson(const std::string &url);
35
#endif
36
};
37
namespace std
38
{
39
40
#ifdef ANDROID
41
template <typename T>
42
int stoi(T s){
43
    return atoi(s.c_str());
44
}
45
#endif
46
47
template <typename T>
48
std::string to_string(T value)
49
2
{
50
2
    std::ostringstream os;
51
2
    os << value;
52
2
    return os.str();
53
2
}
54
} // namespace std
55
56
template <typename T>
57
std::string to_string_with_precision(const T a_value, const int n = 4)
58
78
{
59
78
    std::ostringstream out;
60
78
    out << std::setprecision(n) << a_value;
61
78
    return out.str();
62
78
}
_Z24to_string_with_precisionIdENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEET_i
Line
Count
Source
58
59
{
59
59
    std::ostringstream out;
60
59
    out << std::setprecision(n) << a_value;
61
59
    return out.str();
62
59
}
_Z24to_string_with_precisionIiENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEET_i
Line
Count
Source
58
19
{
59
19
    std::ostringstream out;
60
19
    out << std::setprecision(n) << a_value;
61
19
    return out.str();
62
19
}
63
64
struct Clock{
65
private:
66
    std::time_t m_time;
67
#ifdef BT_TEST
68
    static unsigned int m_BT_H;
69
    static unsigned int m_BT_M;
70
#endif
71
public:
72
    unsigned int m_h = 0;
73
    unsigned int m_min = 0;
74
985
    Clock () {}
75
37
    Clock(std::string t){
76
37
        std::vector<std::string> vt = split_string(t,':');
77
37
        int h = std::stoi(vt.at(0));
78
37
        int m = std::stoi(vt.at(1));
79
37
        set(static_cast <unsigned int>(h),static_cast <unsigned int>(m));
80
37
    }
81
82
702
    Clock(unsigned int h, unsigned int m) {
83
702
        set(h,m);
84
702
    }
85
    /////////////////////////////////////////////////////////////////////////////////////
86
741
    void set(unsigned int h, unsigned int m){
87
741
        if (h<24 && m <60){
88
740
            this->m_h = h;
89
740
            this->m_min = m;
90
740
        }
91
1
        else {
92
1
            throw 0;
93
1
        }
94
740
    }
95
96
    /////////////////////////////////////////////////////////////////////////////////////
97
81
    const std::string getString(){
98
81
        std::stringstream ret;
99
81
        if (m_h < 10) {
100
66
            ret << "0";
101
66
        }
102
81
        ret << m_h;
103
81
        ret << ":";
104
81
        if (m_min < 10) {
105
51
            ret << "0";
106
51
        }
107
81
        ret << m_min;
108
81
        return ret.str();
109
81
    }
110
    /////////////////////////////////////////////////////////////////////////////////////
111
13
    bool operator == (const Clock & c){
112
13
        if ((this->m_h == c.m_h) && (this->m_min == c.m_min)){
113
11
            return true;
114
11
        }
115
2
        else{
116
2
            return false;
117
2
        }
118
13
    }
119
    /////////////////////////////////////////////////////////////////////////////////////
120
13
    bool operator != (const Clock & c){
121
13
        if ((this->m_h != c.m_h) || (this->m_min != c.m_min)){
122
8
            return true;
123
8
        }
124
5
        else{
125
5
            return false;
126
5
        }
127
13
    }
128
    /////////////////////////////////////////////////////////////////////////////////////
129
1
    friend std::ostream & operator<< (std::ostream &w ,  Clock &c) {
130
1
        return w << c.getString();
131
1
    }
132
    /////////////////////////////////////////////////////////////////////////////////////
133
18
    bool operator < (const Clock& c){
134
18
        if (this->m_h < c.m_h){
135
15
            return true;
136
15
        }
137
3
        else{
138
3
            if (this->m_h == c.m_h && this->m_min < c.m_min){
139
1
                return true;
140
1
            }
141
2
        }
142
2
        return false;
143
2
    }
144
    /////////////////////////////////////////////////////////////////////////////////////
145
4
    bool operator > (const Clock& c){
146
4
        if (this->m_h > c.m_h){
147
1
            return true;
148
1
        }
149
3
        else{
150
3
            if (this->m_h == c.m_h && this->m_min > c.m_min){
151
1
                return true;
152
1
            }
153
2
        }
154
2
        return false;
155
2
    }
156
    /////////////////////////////////////////////////////////////////////////////////////
157
5
    bool operator >= (const Clock& c){
158
5
        if (this->m_h > c.m_h){
159
2
            return true;
160
2
        }
161
3
        else if (this->m_h == c.m_h){
162
1
163
1
            if (this->m_min >= c.m_min){
164
1
                return true;
165
1
            }
166
2
        }
167
2
        return false;
168
2
    }
169
    /////////////////////////////////////////////////////////////////////////////////////
170
7
    bool operator <= (const Clock& c){
171
7
        if (this->m_h < c.m_h){
172
2
            return true;
173
2
        }
174
5
        else if (this->m_h == c.m_h){
175
2
176
2
            if (this->m_min <= c.m_min){
177
1
                return true;
178
1
            }
179
4
        }
180
4
        return false;
181
4
    }
182
    /////////////////////////////////////////////////////////////////////////////////////
183
193
    Clock  operator + (const Clock& c){
184
193
        unsigned int minutes, hours;
185
193
        minutes = m_min+ c.m_min;
186
193
        hours = m_h + c.m_h;
187
193
        if (minutes >59){
188
144
            minutes =  minutes % 60;
189
144
            hours+=1;
190
144
        }
191
193
        if (hours >= 24){
192
144
            hours-=24;
193
144
        }
194
193
        return  Clock(hours, minutes);
195
193
196
193
    }
197
    /////////////////////////////////////////////////////////////////////////////////////
198
5
    Clock&  operator += (const Clock& c){
199
5
        unsigned int minutes, hours;
200
5
        minutes = m_min+ c.m_min;
201
5
        hours = m_h + c.m_h;
202
5
        if (minutes >59){
203
4
            minutes =  minutes % 60;
204
4
            hours+=1;
205
4
        }
206
5
        if (hours >= 24){
207
4
            hours-=24;
208
4
        }
209
5
        this->m_h = hours;
210
5
        this->m_min = minutes;
211
5
        return *this;
212
5
213
5
    }
214
    /////////////////////////////////////////////////////////////////////////////////////
215
216
5
    unsigned int toSeconds(){
217
5
        return toSeconds(Clock(this->m_h, this->m_min) );
218
5
    }
219
    /////////////////////////////////////////////////////////////////////////////////////
220
221
6
    static unsigned int toSeconds(Clock t){
222
6
        return ((t.m_h*60) + t.m_min)*60;
223
6
    }
224
    /////////////////////////////////////////////////////////////////////////////////////
225
226
3
    static Clock fromSeconds(unsigned int sec){
227
3
        unsigned int h = sec/3600;
228
3
        unsigned int min = sec%3600;
229
3
        min = min/60;
230
3
        return Clock(h,min);
231
3
    }
232
    /////////////////////////////////////////////////////////////////////////////////////
233
234
    static Clock periodOfTime(Clock start, Clock end)
235
2
    {
236
2
        if (end >= start){
237
1
            return Clock::fromSeconds(end.toSeconds() - start.toSeconds()  );
238
1
        }
239
1
        else{
240
1
            return Clock::fromSeconds(end.toSeconds() + ( Clock::toSeconds(Clock(23,59))+ 60 - start.toSeconds() ) );
241
1
        }
242
2
        //return diff;
243
2
    }
244
    ////////////////////////////////////////////////////////////////////////////////////
245
    static unsigned int getUnixTime()
246
4
    {
247
4
        return static_cast<unsigned int> (std::time(nullptr));
248
4
    }
249
    /////////////////////////////////////////////////////////////////////////////////////
250
#ifdef BT_TEST
251
    static void setTime_forBT_usage(int h, int m)
252
6
    {
253
6
        m_BT_H = h;
254
6
        m_BT_M = m;
255
6
    }
256
#endif
257
    /////////////////////////////////////////////////////////////////////////////////////
258
    static Clock getTime()
259
245
    {
260
245
#ifdef BT_TEST
261
245
        return Clock(m_BT_H,m_BT_M);
262
#else
263
        time_t now = time(0);
264
        tm *ltm = localtime(&now);
265
        return Clock( static_cast <unsigned int>(ltm->tm_hour),static_cast <unsigned int>(ltm->tm_min) );
266
#endif
267
    }
268
    /////////////////////////////////////////////////////////////////////////////////////
269
    void stopwatchStart()
270
1
    {
271
1
        m_time = std::time(nullptr);
272
1
    }
273
    /////////////////////////////////////////////////////////////////////////////////////
274
    unsigned int  stopwatchStopAndGetResult()
275
1
    {
276
1
        return static_cast<unsigned int>(std::time(nullptr) - m_time);
277
1
    }
278
};
279
280
enum class STATE {
281
    OFF,
282
    ON,
283
    UNKNOWN,
284
    PLAY,
285
    PAUSE,
286
    STOP,
287
    ACTIVE,
288
    DEACTIVE,
289
    WORKING,
290
    DEFINE,
291
    UNDEFINE,
292
    LOCK,
293
    UNLOCK,
294
    EMPTY,
295
    FULL,
296
    SEND_OK,
297
    SEND_NOK
298
    //WARNING remember add new state to stateToString() usefull.cpp
299
};
300
301
302
std::string stateToString(STATE s);
303
STATE stringToState(const std::string& s);
304
305
#endif
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/logger/logger.hpp
Line
Count
Source
1
/*
2
 * logger.hpp
3
 *
4
 *
5
 * Logger Library Header
6
 *
7
 *
8
 * Copyright (C) 2013-2014  Bryant Moscon - bmoscon@gmail.com
9
 *
10
 * Permission is hereby granted, free of charge, to any person obtaining a copy
11
 * of this software and associated documentation files (the "Software"), to
12
 * deal in the Software without restriction, including without limitation the
13
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
14
 * sell copies of the Software, and to permit persons to whom the Software is
15
 * furnished to do so, subject to the following conditions:
16
 *
17
 * 1. Redistributions of source code must retain the above copyright notice,
18
 *    this list of conditions, and the following disclaimer.
19
 *
20
 * 2. Redistributions in binary form must reproduce the above copyright notice,
21
 *    this list of conditions and the following disclaimer in the documentation
22
 *    and/or other materials provided with the distribution, and in the same
23
 *    place and form as other copyright, license and disclaimer information.
24
 *
25
 * 3. The end-user documentation included with the redistribution, if any, must
26
 *    include the following acknowledgment: "This product includes software
27
 *    developed by Bryant Moscon (http://www.bryantmoscon.org/)", in the same
28
 *    place and form as other third-party acknowledgments. Alternately, this
29
 *    acknowledgment may appear in the software itself, in the same form and
30
 *    location as other such third-party acknowledgments.
31
 *
32
 * 4. Except as contained in this notice, the name of the author, Bryant Moscon,
33
 *    shall not be used in advertising or otherwise to promote the sale, use or
34
 *    other dealings in this Software without prior written authorization from
35
 *    the author.
36
 *
37
 *
38
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
41
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
42
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
44
 * THE SOFTWARE.
45
 *
46
 */
47
#ifndef __LOGGER__
48
#define __LOGGER__
49
50
#include <fstream>
51
#include <cassert>
52
#include <ctime>
53
#include <sstream>
54
55
// Log levels
56
typedef enum {
57
    US =0,
58
    VERBOSE,
59
    DEBUG,
60
    INFO,
61
    WARNING,
62
    ERROR,
63
    CRITICAL,
64
    FATAL
65
} logger_level;
66
67
class Logger : public std::ostringstream {
68
public:
69
70
    explicit Logger(const char *f);
71
    explicit Logger(const std::string& f);
72
    Logger (const Logger &);
73
    Logger &operator= (const Logger &);
74
    ~Logger();
75
    static pthread_mutex_t mutex_log;
76
77
    void set_level(const logger_level& level);
78
    void flush();
79
    void mutex_lock();
80
    void mutex_unlock();
81
82
    template <typename T>
83
    Logger& operator<<(const T& t)
84
4
    {
85
4
        *static_cast<std::ostringstream *>(this) << t;
86
4
        return (*this);
87
4
    }
_ZN6LoggerlsIA29_cEERS_RKT_
Line
Count
Source
84
2
    {
85
2
        *static_cast<std::ostringstream *>(this) << t;
86
2
        return (*this);
87
2
    }
_ZN6LoggerlsIA25_cEERS_RKT_
Line
Count
Source
84
2
    {
85
2
        *static_cast<std::ostringstream *>(this) << t;
86
2
        return (*this);
87
2
    }
88
89
    Logger& operator<<(const logger_level& level);
90
    typedef Logger& (* LoggerManip)(Logger&);
91
    Logger& operator<<(LoggerManip m);
92
93
private:
94
    std::string get_time() const;
95
    inline const char* level_str(const logger_level& level);
96
public:
97
    std::ofstream _file;
98
private:
99
    std::ostream& _log;
100
    logger_level _level;
101
    logger_level _line_level;
102
};
103
104
105
namespace std { 
106
inline Logger& endl(Logger& out)
107
{
108
    out.put('\n');
109
    out.flush();
110
    return (out);
111
}
112
}// end namespace std
113
114
#endif
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/libs/useful/usefull.cpp
Line
Count
Source (jump to first uncovered line)
1
#include "useful.h"
2
#include <sys/fcntl.h>
3
#include <unistd.h>
4
#include <sys/types.h>
5
#include <sys/stat.h>
6
#include <fcntl.h>
7
#include <fstream>
8
9
#ifndef IDOM
10
#include <curl/curl.h>
11
#endif
12
37
std::vector<std::string> split_string(const std::string& s, char separator ){
13
37
    std::vector<std::string> output;
14
37
    std::string::size_type prev_pos = 0, pos = 0;
15
37
16
74
    while((pos = s.find(separator, pos)) != std::string::npos)
17
37
    {
18
37
        std::string substring( s.substr(prev_pos, pos-prev_pos) );
19
37
        output.push_back(substring);
20
37
        prev_pos = ++pos;
21
37
    }
22
37
    try {
23
37
        output.push_back(s.substr(prev_pos, pos-prev_pos)); // Last word
24
37
    }
25
37
    catch (...){
26
0
27
0
    }
28
37
    return output;
29
37
}
30
31
662
std::string stateToString(STATE s){
32
662
    switch (s) {
33
662
    case STATE::OFF:        return "OFF";
34
662
    case STATE::ON:         return "ON";
35
662
    case STATE::PLAY:       return "PLAY";
36
662
    case STATE::PAUSE:      return "PAUSE";
37
662
    case STATE::STOP:       return "STOP";
38
662
    case STATE::ACTIVE:     return "ACTIVE";
39
662
    case STATE::DEACTIVE:   return "DEACTIVE";
40
662
    case STATE::WORKING:    return "WORKING";
41
662
    case STATE::DEFINE:     return "DEFINE";
42
662
    case STATE::UNDEFINE:   return "UNDEFINE";
43
662
    case STATE::LOCK:       return "LOCK";
44
662
    case STATE::UNLOCK:     return "UNLOCK";
45
662
    case STATE::EMPTY:      return "EMPTY";
46
662
    case STATE::FULL:       return "FULL";
47
662
    case STATE::SEND_OK:    return "SEND_OK";
48
662
    case STATE::SEND_NOK:   return "SEND_NOK";
49
662
    default:
50
42
        return "UNKNOWN";
51
0
    }
52
0
}
53
54
1.94k
STATE stringToState(const std::string& s){
55
1.94k
    if(s == "OFF")
56
386
        return STATE::OFF;
57
1.56k
    else if (s == "ON")
58
386
        return STATE::ON;
59
1.17k
    else if (s == "PLAY")
60
0
        return STATE::PLAY;
61
1.17k
    else if (s == "PAUSE")
62
0
        return STATE::PAUSE;
63
1.17k
    else if (s == "STOP")
64
0
        return STATE::STOP;
65
1.17k
    else if (s == "ACTIVE")
66
0
        return STATE::ACTIVE;
67
1.17k
    else if (s == "DEACTIVE")
68
0
        return STATE::DEACTIVE;
69
1.17k
    else if (s == "WORKING")
70
0
        return STATE::WORKING;
71
1.17k
    else if (s == "DEFINE")
72
0
        return STATE::DEFINE;
73
1.17k
    else if (s == "UNDEFINE")
74
0
        return STATE::UNDEFINE;
75
1.17k
    else if (s == "LOCK")
76
0
        return STATE::LOCK;
77
1.17k
    else if (s == "UNLOCK")
78
0
        return STATE::UNLOCK;
79
1.17k
    else if (s == "EMPTY")
80
0
        return STATE::EMPTY;
81
1.17k
    else if (s == "FULL")
82
0
        return STATE::FULL;
83
1.17k
    else if (s == "SEND_OK")
84
0
        return STATE::SEND_OK;
85
1.17k
    else if (s == "SEND_NOK")
86
0
        return STATE::SEND_NOK;
87
1.17k
    else
88
1.17k
        return STATE::UNKNOWN;
89
0
}
90
91
#ifndef IDOM
92
void useful_F_libs::write_to_mkfifo(const std::string &path, const std::string& msg)
93
6
{
94
6
    errno = 0;
95
6
    int fd = open(path.c_str(), O_RDWR| O_NONBLOCK );
96
6
    std::cout << "write open file: " << fd << " path " << path.c_str() << " msg: " << msg <<std::endl;
97
6
    std::cout << "write_to_mkfifo( error - " << strerror(  errno ) <<   std::endl;
98
6
    write(fd, msg.c_str(), msg.size());
99
6
    close(fd);
100
6
}
101
102
std::string useful_F_libs::read_from_mkfifo(const std::string& path)
103
11
{
104
11
    /* char buf[10];
105
11
    //open, read, and display the message from the FIFO
106
11
    int fd = open(path.c_str(), O_RDONLY | O_NONBLOCK);
107
11
    std::cout <<"read open file: " << fd <<std::endl;
108
11
    read(fd, buf, sizeof (buf));
109
11
    std::cout << "buf: " << buf << std::endl;
110
11
    close(fd);
111
11
    return (std::string(buf));
112
11
*/    std::string buf = "NULL";
113
11
    std::fstream fd;
114
11
    fd.open(path.c_str(), std::fstream::in | std::fstream::out | std::fstream::app);
115
11
116
11
    std::getline(fd,buf);
117
11
    return buf;
118
11
}
119
120
size_t useful_F_libs::WriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
121
25
{
122
25
    ((std::string*)userp)->append((char*)contents, size * nmemb);
123
25
    return size * nmemb;
124
25
}
125
126
std::string useful_F_libs::find_tag(const std::string& temp)
127
14
{
128
14
    std::string value = "";
129
294
    for (unsigned int i = 0; i<temp.size();++i){
130
294
131
294
        if (temp.at(i) =='>')
132
14
        {  int z = i+1;
133
42
            while (temp.at(z)!='<')
134
28
            {
135
28
                value+= temp.at(z);
136
28
                ++z;
137
28
            }
138
14
            break;
139
14
        }
140
294
    }
141
14
    return value;
142
14
}
143
144
#ifndef BT_TEST
145
std::string useful_F_libs::httpPost(const std::string& url, int timeoutSeconds)
146
{
147
    CURL *curl;
148
    CURLcode res;
149
    std::string readBuffer;
150
    curl = curl_easy_init();
151
152
    if(curl) {
153
        curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeoutSeconds);
154
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
155
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, useful_F_libs::WriteCallback);
156
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
157
        res = curl_easy_perform(curl);
158
        /* Check for errors */
159
        if(res != CURLE_OK)
160
            fprintf(stderr, "curl_easy_perform() failed: %s\n",
161
                    curl_easy_strerror(res));
162
163
        /* always cleanup */
164
        curl_easy_cleanup(curl);
165
    }
166
    curl_global_cleanup();
167
168
    return readBuffer;
169
}
170
171
std::string useful_F_libs::httpPost(const std::string& url)
172
{
173
    return useful_F_libs::httpPost(url, 10);
174
}
175
#endif
176
177
void useful_F_libs::downloadFile(const std::string& url, const std::string& path, int timeoutSeconds)
178
0
{
179
0
    CURL *curl;
180
0
    //CURLcode res;
181
0
182
0
    curl = curl_easy_init();
183
0
    if (curl) {
184
0
        FILE *fp = fopen(path.c_str(),"wb");
185
0
        curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeoutSeconds);
186
0
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
187
0
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NULL);
188
0
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
189
0
        //res = curl_easy_perform(curl);
190
0
        /* always cleanup */
191
0
        curl_easy_cleanup(curl);
192
0
        fclose(fp);
193
0
    }
194
0
}
195
196
3
std::string useful_F_libs::replaceAll(std::string str, const std::string& from, const std::string& to) {
197
3
    size_t start_pos = 0;
198
11
    while((start_pos = str.find(from, start_pos)) != std::string::npos) {
199
8
        str.replace(start_pos, from.length(), to);
200
8
        start_pos += to.length(); // Handles case where 'to' is a substring of 'from'
201
8
    }
202
3
    return str;
203
3
}
204
std::string useful_F_libs::removeHtmlTag(std::string &data)
205
2
{
206
2
    data = useful_F_libs::replaceAll(data,"</dl>","\n");
207
2
208
2
    //data = useful_F::replaceAll(data,"    "," ");
209
2
    bool copy = true;
210
2
    std::string plainString = "";
211
2
    std::stringstream convertStream;
212
2
213
2
    // remove all xml tags
214
2.88k
    for (unsigned int i=0; i < data.length(); i++)
215
2.87k
    {
216
2.87k
        convertStream << data[i];
217
2.87k
218
2.87k
        if(convertStream.str().compare("<") == 0) copy = false;
219
2.85k
        else if(convertStream.str().compare(">") == 0)
220
19
        {
221
19
            copy = true;
222
19
            convertStream.str(std::string());
223
19
            continue;
224
19
        }
225
2.85k
226
2.85k
        if(copy) plainString.append(convertStream.str());
227
2.85k
228
2.85k
        convertStream.str(std::string());
229
2.85k
    }
230
2
231
2
    return plainString;
232
2
}
233
234
nlohmann::json useful_F_libs::getJson(const std::string& url)
235
4
{
236
4
    std::string str = useful_F_libs::httpPost(url);
237
4
    nlohmann::json jj = nlohmann::json::parse( str);
238
4
239
4
    return jj;
240
4
}
241
#endif
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDom_server_OOP.h
Line
Count
Source
1
#ifndef GLOBAL_H
2
#define GLOBAL_H
3
4
#include <iostream>
5
#include <fstream>
6
#include <string>
7
#include <cstdlib>
8
#include <pthread.h>
9
#include <stdio.h>
10
#include <stdlib.h>
11
#include <sys/socket.h>
12
#include <sys/types.h>
13
#include <netinet/in.h>
14
#include <vector>
15
#include <thread>
16
#include <arpa/inet.h>
17
#include <netinet/in.h>
18
#include <unistd.h>
19
#include <sys/fcntl.h>
20
#include <unistd.h>
21
#include <errno.h>
22
#include <signal.h>
23
#include <time.h>
24
#include <wiringPi.h>
25
#include <chrono>
26
#include <array>
27
28
// MOJE BIBLIOTEKI
29
#include "KEY/key.h"
30
#include "logger/logger.hpp"
31
#include "files_tree/files_tree.h"
32
#include "menu_tree/menu_tree.h"
33
#include "LCD_c/lcd_c.h"
34
#include "command/command.h"
35
#include "../libs/event_counters/event_counters_handler.h"
36
#include "iDomTools/idomtools.h"
37
#include "iDomStatus/idomstatus.h"
38
#include "iDomSaveState/idom_save_state.h"
39
40
17
#define log_file_cout  f_log //std::cout zmien f_log na std::cout i bedzie wypisywac na ekran
41
6
#define log_file_mutex f_log
42
43
enum class iDomStateEnum{
44
    CLOSE = 0,
45
    RELOAD,
46
    ERROR,
47
    WORKING,
48
    HARD_RELOAD
49
};
50
51
namespace iDomConst
52
{
53
constexpr int MAX_CONNECTION = 10;
54
constexpr int FREE  = 1;
55
constexpr int RS232 = 11;
56
constexpr int CLOCK = 12;
57
constexpr int ok    = 0;
58
constexpr int GPIO_SPIK = 21;
59
constexpr int GPIO_PRINTER = 22;
60
constexpr int BUTTON_PIN = 25;
61
}
62
struct ALERT
63
{
64
    Clock time;
65
    STATE state = STATE::DEACTIVE;
66
    unsigned int fromVolume = 48;
67
    unsigned int toVolume = 58;
68
    unsigned int radioID = 8;
69
};
70
71
extern std::string _logfile;
72
extern Logger log_file_mutex;
73
extern std::string buffer;
74
75
enum class TEMPERATURE_STATE;
76
enum class PILOT_KEY;
77
78
struct MPD_info{
79
    std::string title   = "NULL";
80
    std::string radio   = "NULL";
81
    std::string artist  = "NULL";
82
    int volume = 0;
83
    bool isPlay = false;
84
    int currentSongID = 0;
85
    std::vector <std::string> songList = {"NULL"};
86
};
87
struct s_pointer{
88
    unsigned int *ptr_who;
89
    int32_t *ptr_buf;
90
};
91
92
struct Thread_array_struc {
93
    std::thread thread;
94
    std::thread::id thread_ID = std::thread::id(0);
95
    std::string thread_name;
96
    int thread_socket = 0;
97
};
98
99
struct address_another_servers {
100
    int id;
101
    std::string SERVER_IP;
102
};
103
104
struct FTP_SERVER{
105
    std::string URL;
106
    std::string user;
107
    std::string pass;
108
};
109
struct iDOM_STATE{
110
    STATE houseState = STATE::UNDEFINE;
111
112
};
113
114
struct config{
115
    std::string portRS232;
116
    std::string portRS232_clock;
117
    std::string BaudRate;
118
    std::string RFLinkPort;
119
    std::string RFLinkBaudRate;
120
    int PORT;
121
    std::string SERVER_IP;
122
    std::string MPD_IP;
123
    std::string MOVIES_DB_PATH;
124
    std::string MENU_PATH;
125
    std::string THREAD_MPD   = "NULL";
126
    std::string THREAD_IRDA  = "NULL";
127
    std::string THREAD_CRON  = "NULL";
128
    std::string THREAD_RS232 = "NULL";
129
    std::string THREAD_DUMMY = "NULL";
130
    std::string TS_KEY= " gg ";
131
    std::string cameraLedON = "";
132
    std::string cameraLedOFF ="";
133
    std::string cameraURL="";
134
    std::string facebookAccessToken = "";
135
    std::string viberToken = "NULL";
136
    std::string viberAvatar;
137
    std::vector <std::string> viberReceiver;
138
    std::string viberSender;
139
    std::string radio433MHzConfigFile;
140
    std::string omxplayerFile = "NULL";
141
    int ID_server = 0;
142
    int v_delay;
143
    bool encrypted = true;
144
145
    FTP_SERVER ftpServer;
146
    std::string lightningApiURL = "NULL";
147
    std::string saveFilePath = "NULL";
148
};
149
150
struct LED_Strip{
151
    std::string from;
152
    std::string to;
153
    std::string R;
154
    std::string G;
155
    std::string B;
156
    std::string colorName;
157
158
    LED_Strip (int from, int to, int r, int g, int b, std::string colorName = "NULL"):from(std::to_string(from)),
159
        to(std::to_string(to)),
160
        R(std::to_string(r)),
161
        G(std::to_string(g)),
162
        B(std::to_string(b)),
163
        colorName(colorName)
164
    {
165
166
    }
167
    LED_Strip (const std::string& from,
168
               const std::string& to,
169
               const std::string& r,
170
               const std::string& g,
171
               const std::string& b,
172
               const std::string& colorName = "NULL"):
173
        from(from),
174
        to(to),
175
        R(r),
176
        G(g),
177
        B(b),
178
        colorName(colorName)
179
    {
180
181
    }
182
183
    void set (const std::string& from,
184
              const std::string& to,
185
              const std::string& r,
186
              const std::string& g,
187
              const std::string& b,
188
              const std::string& colorName = "NULL")
189
    {
190
        this->from =from;
191
        this->to = to;
192
        R = r;
193
        G = g;
194
        B = b;
195
        this->colorName =colorName;
196
    }
197
198
    void set (int from, int to, int r, int g, int b, std::string colorName = "NULL"){
199
        this->from = std::to_string(from);
200
        this->to = std::to_string(to);
201
        R = std::to_string(r);
202
        G = std::to_string(g);
203
        B = std::to_string(b);
204
        this->colorName =colorName;
205
    }
206
207
    std::string getColorName() const{
208
        return colorName;
209
    }
210
211
    std::string get(unsigned int _from, unsigned int _to) const{
212
        if (_from != 0 || _to != 60){
213
            return "LED:["+std::to_string(_from)+"-"+std::to_string(_to)+"-"+R+"-"+G+"-"+B+"];";
214
        }
215
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
216
    }
217
218
    std::string makeCommand(const std::string& from,
219
                            const std::string& to,
220
                            const std::string& R,
221
                            const std::string& G,
222
                            const std::string& B){
223
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
224
    }
225
};
226
227
struct pilot_led{
228
    unsigned int counter=0;
229
    std::vector<LED_Strip> colorLED   = { LED_Strip(1,60,237,145,33 ,"carrot orange"),
230
                                          LED_Strip(1,60,255,0,0    ,"red"),
231
                                          LED_Strip(1,60,0,255,0    ,"green"),
232
                                          LED_Strip(1,60,0,0,255    ,"blue"),
233
                                          LED_Strip(1,60,255,255,255,"white"),
234
                                          LED_Strip(1,60,255,255,0  ,"yellow"),
235
                                          LED_Strip(1,60,0,255,255  ,"cyan"),
236
                                          LED_Strip(1,60,255,0,255  ,"magenta")
237
                                        };
238
};
239
240
class command; // for struc thread_data req
241
class iDomTOOLS;
242
class RADIO_EQ_CONTAINER;
243
class RFLinkHandler;
244
245
struct thread_data{
246
    int s_client_sock;
247
    struct sockaddr_in from;
248
    struct config *server_settings = NULL;
249
    struct s_pointer pointer;
250
    LCD_c *mainLCD = NULL;
251
    files_tree *main_tree = NULL;
252
    menu_tree *main_MENU = NULL;
253
    iDomTOOLS *main_iDomTools = NULL;
254
    RFLinkHandler *main_RFLink = NULL;
255
    std::array<Thread_array_struc, iDomConst::MAX_CONNECTION> *main_THREAD_arr = NULL;
256
    time_t start;
257
    time_t now_time;
258
    int sleeper;
259
    std::map <std::string, std::unique_ptr <KEY> > key_map;
260
    MPD_info *ptr_MPD_info = NULL;
261
    pilot_led * ptr_pilot_led = NULL;
262
    std::map <std::string, std::unique_ptr<command> >* commandMapPtr = NULL;
263
    event_counters_handler myEventHandler;
264
    std::string encriptionKey = "40%";
265
    iDomSTATUS *main_iDomStatus;
266
    iDOM_STATE idom_all_state;
267
    ALERT alarmTime;
268
    std::shared_ptr<RADIO_EQ_CONTAINER> main_REC;
269
    iDomStateEnum iDomProgramState = iDomStateEnum::WORKING;
270
};
271
272
struct thread_data_rs232{
273
    std::string portRS232;
274
    std::string portRS232_clock;
275
    std::string BaudRate;
276
    struct s_pointer pointer;
277
};
278
279
#endif // GLOBAL_H
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/433MHz/RFLink/TEST/rflinkhandler_BT.cpp
Line
Count
Source
1
#include <gtest/gtest.h>
2
3
#include "../rflinkhandler.h"
4
#include "test_data.h"
5
6
class RFLinkHandler_Class_fixture : public ::testing::Test
7
{
8
public:
9
    thread_data test_my_data;
10
    config test_server_set;
11
    iDomSTATUS test_status;
12
    std::unique_ptr<RFLinkHandler> test_RFLink;
13
14
    void SetUp() final
15
5
    {
16
5
        test_server_set.TS_KEY = "key test";
17
5
        test_server_set.RFLinkBaudRate = "57600";
18
5
        test_server_set.RFLinkPort = "/dev/fakePortRS232";
19
5
        test_my_data.server_settings = &test_server_set;
20
5
        test_my_data.main_iDomStatus = &test_status;
21
5
        test_RFLink = std::make_unique<RFLinkHandler>(&test_my_data);
22
5
    }
23
    void TearDown() final
24
5
    {
25
5
    }
26
};
27
28
TEST_F(RFLinkHandler_Class_fixture, sendCommandAndWaitForReceive)
29
1
{
30
1
    test_RFLink->init();
31
1
    std::string k("msg_test;\n a=4:b=10;\n");
32
1
    SerialPi_set_recv_msg(k);
33
1
    std::string r = test_RFLink->sendCommandAndWaitForReceive("test command");
34
1
35
1
    EXPECT_STREQ(r.c_str(),"msg_test;");
36
1
    r = test_RFLink->sendCommandAndWaitForReceive("ok");
37
1
    EXPECT_STREQ(r.c_str()," a=4:b=10;");
38
1
}
39
40
TEST_F(RFLinkHandler_Class_fixture, port_does_not_exist)
41
1
{
42
1
    bool result =  test_RFLink->init();
43
1
    EXPECT_FALSE(result);
44
1
}
45
46
TEST_F(RFLinkHandler_Class_fixture, port_exist)
47
1
{
48
1
    test_server_set.RFLinkPort = "/dev/tty0";
49
1
    bool result =  test_RFLink->init();
50
1
    EXPECT_TRUE(result);
51
1
}
52
53
TEST_F(RFLinkHandler_Class_fixture, getValue)
54
1
{
55
1
    std::string m  = "20;90;Alecto V4;ID=557a;TEMP=0057;HUM=25;";
56
1
    EXPECT_STREQ(test_RFLink->getArgumentValueFromRFLinkMSG(m,"ID").c_str(),"557a");
57
1
    EXPECT_STREQ(test_RFLink->getArgumentValueFromRFLinkMSG(m,"TEMP").c_str(),"0057");
58
1
    EXPECT_THROW(test_RFLink->getArgumentValueFromRFLinkMSG(m,"test"),std::string);
59
1
}
60
61
TEST_F(RFLinkHandler_Class_fixture, readAndFlush)
62
1
{
63
1
    SerialPi_set_recv_msg("doTest;\n");
64
1
    std::string retStr = test_RFLink->readFromRS232();
65
1
    EXPECT_STREQ(retStr.c_str(), "doTest;");
66
1
67
1
    SerialPi_set_recv_msg("doTest2;\n");
68
1
    test_RFLink->flush();
69
1
    retStr = test_RFLink->readFromRS232();
70
1
    EXPECT_EQ(retStr.size(), 0);
71
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/433MHz/RFLink/TEST/rflinkhandler_BT.cpp
Line
Count
Source
1
#include <gtest/gtest.h>
2
3
#include "../rflinkhandler.h"
4
#include "test_data.h"
5
6
class RFLinkHandler_Class_fixture : public ::testing::Test
7
{
8
public:
9
    thread_data test_my_data;
10
    config test_server_set;
11
    iDomSTATUS test_status;
12
    std::unique_ptr<RFLinkHandler> test_RFLink;
13
14
    void SetUp() final
15
5
    {
16
5
        test_server_set.TS_KEY = "key test";
17
5
        test_server_set.RFLinkBaudRate = "57600";
18
5
        test_server_set.RFLinkPort = "/dev/fakePortRS232";
19
5
        test_my_data.server_settings = &test_server_set;
20
5
        test_my_data.main_iDomStatus = &test_status;
21
5
        test_RFLink = std::make_unique<RFLinkHandler>(&test_my_data);
22
5
    }
23
    void TearDown() final
24
5
    {
25
5
    }
26
};
27
28
TEST_F(RFLinkHandler_Class_fixture, sendCommandAndWaitForReceive)
29
1
{
30
1
    test_RFLink->init();
31
1
    std::string k("msg_test;\n a=4:b=10;\n");
32
1
    SerialPi_set_recv_msg(k);
33
1
    std::string r = test_RFLink->sendCommandAndWaitForReceive("test command");
34
1
35
1
    EXPECT_STREQ(r.c_str(),"msg_test;");
36
1
    r = test_RFLink->sendCommandAndWaitForReceive("ok");
37
1
    EXPECT_STREQ(r.c_str()," a=4:b=10;");
38
1
}
39
40
TEST_F(RFLinkHandler_Class_fixture, port_does_not_exist)
41
1
{
42
1
    bool result =  test_RFLink->init();
43
1
    EXPECT_FALSE(result);
44
1
}
45
46
TEST_F(RFLinkHandler_Class_fixture, port_exist)
47
1
{
48
1
    test_server_set.RFLinkPort = "/dev/tty0";
49
1
    bool result =  test_RFLink->init();
50
1
    EXPECT_TRUE(result);
51
1
}
52
53
TEST_F(RFLinkHandler_Class_fixture, getValue)
54
1
{
55
1
    std::string m  = "20;90;Alecto V4;ID=557a;TEMP=0057;HUM=25;";
56
1
    EXPECT_STREQ(test_RFLink->getArgumentValueFromRFLinkMSG(m,"ID").c_str(),"557a");
57
1
    EXPECT_STREQ(test_RFLink->getArgumentValueFromRFLinkMSG(m,"TEMP").c_str(),"0057");
58
1
    EXPECT_THROW(test_RFLink->getArgumentValueFromRFLinkMSG(m,"test"),std::string);
59
1
}
60
61
TEST_F(RFLinkHandler_Class_fixture, readAndFlush)
62
1
{
63
1
    SerialPi_set_recv_msg("doTest;\n");
64
1
    std::string retStr = test_RFLink->readFromRS232();
65
1
    EXPECT_STREQ(retStr.c_str(), "doTest;");
66
1
67
1
    SerialPi_set_recv_msg("doTest2;\n");
68
1
    test_RFLink->flush();
69
1
    retStr = test_RFLink->readFromRS232();
70
    EXPECT_EQ(retStr.size(), 0);
71
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/433MHz/RFLink/rflinkhandler.cpp
Line
Count
Source
1
#include <unistd.h>
2
3
#include "rflinkhandler.h"
4
#include "../../functions/functions.h"
5
6
std::mutex RFLinkHandler::sm_RFLink_MUTEX;
7
std::string RFLinkHandler::sm_RFLink_BUFOR;
8
9
10
RFLinkHandler::RFLinkHandler(thread_data *my_data):
11
    serial_RFLink(my_data->server_settings->RFLinkPort)
12
50
{
13
50
    this->my_data = my_data;
14
50
#ifdef BT_TEST
15
50
    std::cout << "RFLinkHandler::RFLinkHandler()"<<std::endl;
16
50
#endif
17
50
}
18
19
bool RFLinkHandler::init()
20
3
{
21
3
    if( access( my_data->server_settings->RFLinkPort.c_str(), F_OK ) != -1 )
22
1
    {
23
1
        serial_RFLink.begin( std::stoi(my_data->server_settings->RFLinkBaudRate));
24
1
        log_file_mutex.mutex_lock();
25
1
        log_file_cout << INFO <<"otwarcie portu RS232 RFLink " << my_data->server_settings->RFLinkPort << "  "
26
1
                      <<my_data->server_settings->RFLinkBaudRate<<std::endl;
27
1
        log_file_mutex.mutex_unlock();
28
1
        return true;
29
1
    }
30
2
    else
31
2
    {
32
2
        log_file_mutex.mutex_lock();
33
2
        log_file_cout << ERROR <<"brak portu RS232 RFLink " << my_data->server_settings->RFLinkPort<<std::endl;
34
2
        log_file_mutex.mutex_unlock();
35
2
        return false;
36
2
    }
37
3
}
38
39
void RFLinkHandler::flush()
40
1
{
41
1
    serial_RFLink.flush();
42
1
}
43
44
void RFLinkHandler::sendCommand(std::string cmd)
45
1
{
46
1
    std::lock_guard<std::mutex> m_lock(sm_RFLink_MUTEX);
47
1
    cmd.append("\n\r"); // add NL & CR
48
1
    serial_RFLink.print(cmd.c_str());
49
1
}
50
51
std::string RFLinkHandler::sendCommandAndWaitForReceive(std::string cmd)
52
2
{
53
2
    std::lock_guard<std::mutex> m_lock(sm_RFLink_MUTEX);
54
2
    cmd.append("\n\r"); // add NL & CR
55
2
    serial_RFLink.print(cmd.c_str());
56
2
    return internalReadFromRS232();
57
2
}
58
59
std::string RFLinkHandler::readFromRS232()
60
2
{
61
2
    std::lock_guard<std::mutex> m_lock(sm_RFLink_MUTEX);
62
2
    return internalReadFromRS232();
63
2
}
64
65
std::string RFLinkHandler::internalReadFromRS232()
66
4
{
67
4
    std::string buf;
68
4
69
4
    if(serial_RFLink.available() > 0){
70
29
        while (true){
71
29
72
29
            char b = serial_RFLink.read();
73
29
            if (b == '\n'){
74
3
                break;
75
3
            }
76
26
            buf += b;
77
26
        }
78
3
    }
79
4
    return buf;
80
4
}
81
82
std::string RFLinkHandler::getArgumentValueFromRFLinkMSG(const std::string& msg, const std::string& var)
83
64
{
84
64
    std::string id;
85
64
86
64
    int pos = msg.find(var+"=");
87
64
    if (pos == -1 ){
88
19
        throw "argument \""+var+"\" not found";
89
19
    }
90
45
    if (msg.at(0) != '2' || msg.at(1) != '0'){
91
1
        throw WRONG_FORMAT();
92
1
    }
93
44
#ifdef BT_TEST
94
44
    std::cout << "znaleziono " << var <<" na pozycji " << pos <<std::endl;
95
44
#endif
96
44
97
265
    for (int i = 1+pos+var.size();;++i ){
98
265
        char t = msg.at(i);
99
265
        if (t ==';'){
100
44
            break;
101
44
        }
102
221
        id += t;
103
221
    }
104
44
    return id;
105
44
106
44
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/433MHz/RFLink/rflinkhandler.cpp
Line
Count
Source
1
#include <unistd.h>
2
3
#include "rflinkhandler.h"
4
#include "../../functions/functions.h"
5
6
std::mutex RFLinkHandler::sm_RFLink_MUTEX;
7
std::string RFLinkHandler::sm_RFLink_BUFOR;
8
9
10
RFLinkHandler::RFLinkHandler(thread_data *my_data):
11
    serial_RFLink(my_data->server_settings->RFLinkPort)
12
50
{
13
50
    this->my_data = my_data;
14
50
#ifdef BT_TEST
15
50
    std::cout << "RFLinkHandler::RFLinkHandler()"<<std::endl;
16
50
#endif
17
50
}
18
19
bool RFLinkHandler::init()
20
3
{
21
3
    if( access( my_data->server_settings->RFLinkPort.c_str(), F_OK ) != -1 )
22
3
    {
23
1
        serial_RFLink.begin( std::stoi(my_data->server_settings->RFLinkBaudRate));
24
1
        log_file_mutex.mutex_lock();
25
1
        log_file_cout << INFO <<"otwarcie portu RS232 RFLink " << my_data->server_settings->RFLinkPort << "  "
26
1
                      <<my_data->server_settings->RFLinkBaudRate<<std::endl;
27
1
        log_file_mutex.mutex_unlock();
28
1
        return true;
29
1
    }
30
3
    else
31
3
    {
32
2
        log_file_mutex.mutex_lock();
33
2
        log_file_cout << ERROR <<"brak portu RS232 RFLink " << my_data->server_settings->RFLinkPort<<std::endl;
34
2
        log_file_mutex.mutex_unlock();
35
2
        return false;
36
2
    }
37
3
}
38
39
void RFLinkHandler::flush()
40
1
{
41
1
    serial_RFLink.flush();
42
1
}
43
44
void RFLinkHandler::sendCommand(std::string cmd)
45
1
{
46
1
    std::lock_guard<std::mutex> m_lock(sm_RFLink_MUTEX);
47
1
    cmd.append("\n\r"); // add NL & CR
48
1
    serial_RFLink.print(cmd.c_str());
49
1
}
50
51
std::string RFLinkHandler::sendCommandAndWaitForReceive(std::string cmd)
52
2
{
53
2
    std::lock_guard<std::mutex> m_lock(sm_RFLink_MUTEX);
54
2
    cmd.append("\n\r"); // add NL & CR
55
2
    serial_RFLink.print(cmd.c_str());
56
2
    return internalReadFromRS232();
57
2
}
58
59
std::string RFLinkHandler::readFromRS232()
60
2
{
61
2
    std::lock_guard<std::mutex> m_lock(sm_RFLink_MUTEX);
62
2
    return internalReadFromRS232();
63
2
}
64
65
std::string RFLinkHandler::internalReadFromRS232()
66
4
{
67
4
    std::string buf;
68
4
69
4
    if(serial_RFLink.available() > 0){
70
29
        while (true){
71
29
72
29
            char b = serial_RFLink.read();
73
29
            if (b == '\n'){
74
3
                break;
75
3
            }
76
29
            buf += b;
77
26
        }
78
3
    }
79
4
    return buf;
80
4
}
81
82
std::string RFLinkHandler::getArgumentValueFromRFLinkMSG(const std::string& msg, const std::string& var)
83
64
{
84
64
    std::string id;
85
64
86
64
    int pos = msg.find(var+"=");
87
64
    if (pos == -1 ){
88
19
        throw "argument \""+var+"\" not found";
89
19
    }
90
64
    if (msg.at(0) != '2' || msg.at(1) != '0'){
91
1
        throw WRONG_FORMAT();
92
1
    }
93
45
#ifdef BT_TEST
94
45
    std::cout << "znaleziono " << var <<" na pozycji " << pos <<std::endl;
95
44
#endif
96
44
97
265
    for (int i = 1+pos+var.size();;++i ){
98
265
        char t = msg.at(i);
99
265
        if (t ==';'){
100
44
            break;
101
44
        }
102
265
        id += t;
103
221
    }
104
44
    return id;
105
45
106
45
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/433MHz/RFLink/rflinkhandler.h
Line
Count
Source
1
#ifndef RFLINKHANDLER_H
2
#define RFLINKHANDLER_H
3
4
#include <map>
5
#include <exception>
6
#include "../../SerialPi/serialpi.h"
7
#include "../../iDom_server_OOP.h"
8
9
class WRONG_FORMAT : public std::exception{
10
11
};
12
13
struct RFLink_DEV{
14
    int m_counter = 0;
15
    std::string msg;
16
9
    void counter(){
17
9
        ++m_counter;
18
9
    }
19
20
2
    std::string read(){
21
2
        return std::to_string(m_counter) + " \t"+ msg;
22
2
    }
23
};
24
25
class RFLinkHandler
26
{
27
    thread_data *my_data;
28
    SerialPi serial_RFLink;
29
30
public:
31
32
    static std::mutex sm_RFLink_MUTEX;
33
    static std::string sm_RFLink_BUFOR;
34
35
    unsigned int okTime = 0;
36
    unsigned int pingTime = 0;
37
    ////// temporarnie //////
38
    std::map<std::string, RFLink_DEV> rflinkMAP;
39
    /////////////////////////////
40
    RFLinkHandler(thread_data *my_data);
41
42
    bool init();
43
    // void run();
44
    void flush();
45
    void sendCommand(std::string cmd);
46
    std::string sendCommandAndWaitForReceive(std::string cmd);
47
    std::string readFromRS232();
48
private:
49
    std::string internalReadFromRS232();
50
//#ifdef BT_TEST
51
public:
52
//#endif
53
    static std::string getArgumentValueFromRFLinkMSG(const std::string &msg, const std::string &var);
54
};
55
56
#endif // RFLINKHANDLER_H
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/LCD_c/test/lcd_c_stub.cpp
Line
Count
Source
1
#include <iostream>
2
#include "../lcd_c.h"
3
4
55
void LCD_c::set_print_song_state(int i){
5
55
    std::cout << "LCD_c::set_print_song_state(int i)" << i <<std::endl;
6
55
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/LCD_c/test/lcd_c_stub.cpp
Line
Count
Source
1
#include <iostream>
2
#include "../lcd_c.h"
3
4
55
void LCD_c::set_print_song_state(int i){
5
55
    std::cout << "LCD_c::set_print_song_state(int i)" << i <<std::endl;
6
55
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/logger/logger.hpp
Line
Count
Source
1
/*
2
 * logger.hpp
3
 *
4
 *
5
 * Logger Library Header
6
 *
7
 *
8
 * Copyright (C) 2013-2014  Bryant Moscon - bmoscon@gmail.com
9
 *
10
 * Permission is hereby granted, free of charge, to any person obtaining a copy
11
 * of this software and associated documentation files (the "Software"), to
12
 * deal in the Software without restriction, including without limitation the
13
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
14
 * sell copies of the Software, and to permit persons to whom the Software is
15
 * furnished to do so, subject to the following conditions:
16
 *
17
 * 1. Redistributions of source code must retain the above copyright notice,
18
 *    this list of conditions, and the following disclaimer.
19
 *
20
 * 2. Redistributions in binary form must reproduce the above copyright notice,
21
 *    this list of conditions and the following disclaimer in the documentation
22
 *    and/or other materials provided with the distribution, and in the same
23
 *    place and form as other copyright, license and disclaimer information.
24
 *
25
 * 3. The end-user documentation included with the redistribution, if any, must
26
 *    include the following acknowledgment: "This product includes software
27
 *    developed by Bryant Moscon (http://www.bryantmoscon.org/)", in the same
28
 *    place and form as other third-party acknowledgments. Alternately, this
29
 *    acknowledgment may appear in the software itself, in the same form and
30
 *    location as other such third-party acknowledgments.
31
 *
32
 * 4. Except as contained in this notice, the name of the author, Bryant Moscon,
33
 *    shall not be used in advertising or otherwise to promote the sale, use or
34
 *    other dealings in this Software without prior written authorization from
35
 *    the author.
36
 *
37
 *
38
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
41
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
42
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
44
 * THE SOFTWARE.
45
 *
46
 */
47
#ifndef __LOGGER__
48
#define __LOGGER__
49
50
#include <fstream>
51
#include <cassert>
52
#include <ctime>
53
#include <sstream>
54
55
// Log levels
56
typedef enum {
57
    US =0,
58
    VERBOSE,
59
    DEBUG,
60
    INFO,
61
    WARNING,
62
    ERROR,
63
    CRITICAL,
64
    FATAL
65
} logger_level;
66
67
class Logger : public std::ostringstream {
68
public:
69
70
    explicit Logger(const char *f);
71
    explicit Logger(const std::string& f);
72
    Logger (const Logger &);
73
    Logger &operator= (const Logger &);
74
    ~Logger();
75
    static pthread_mutex_t mutex_log;
76
77
    void set_level(const logger_level& level);
78
    void flush();
79
    void mutex_lock();
80
    void mutex_unlock();
81
82
    template <typename T>
83
    Logger& operator<<(const T& t)
84
7
    {
85
7
        *static_cast<std::ostringstream *>(this) << t;
86
7
        return (*this);
87
7
    }
_ZN6LoggerlsIA30_cEERS_RKT_
Line
Count
Source
84
2
    {
85
2
        *static_cast<std::ostringstream *>(this) << t;
86
2
        return (*this);
87
2
    }
_ZN6LoggerlsIA31_cEERS_RKT_
Line
Count
Source
84
3
    {
85
3
        *static_cast<std::ostringstream *>(this) << t;
86
3
        return (*this);
87
3
    }
_ZN6LoggerlsIA39_cEERS_RKT_
Line
Count
Source
84
2
    {
85
2
        *static_cast<std::ostringstream *>(this) << t;
86
2
        return (*this);
87
2
    }
88
89
    Logger& operator<<(const logger_level& level);
90
    typedef Logger& (* LoggerManip)(Logger&);
91
    Logger& operator<<(LoggerManip m);
92
93
private:
94
    std::string get_time() const;
95
    inline const char* level_str(const logger_level& level);
96
public:
97
    std::ofstream _file;
98
private:
99
    std::ostream& _log;
100
    logger_level _level;
101
    logger_level _line_level;
102
};
103
104
105
namespace std { 
106
inline Logger& endl(Logger& out)
107
{
108
    out.put('\n');
109
    out.flush();
110
    return (out);
111
}
112
}// end namespace std
113
114
#endif
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/RADIO_433_eq/radio_433_eq.cpp
Line
Count
Source (jump to first uncovered line)
1
#include <iostream>
2
#include <fstream>
3
#include <sstream>
4
#include "radio_433_eq.h"
5
6
RADIO_SWITCH::RADIO_SWITCH(thread_data *my_data, const RADIO_EQ_CONFIG &cfg, RADIO_EQ_TYPE type):
7
    main433MHz(my_data)
8
973
{
9
973
    puts("RADIO_SWITCH::RADIO_SWITCH()");
10
973
    RADIO_EQ::m_my_data = my_data;
11
973
    RADIO_EQ::m_type = type;
12
973
    RADIO_EQ::m_config = cfg;
13
973
    m_sunrise = stringToState(cfg.sunrise);
14
973
    m_sunset  = stringToState(cfg.sunset);
15
973
}
16
17
RADIO_SWITCH::~RADIO_SWITCH()
18
973
{
19
973
    puts("RADIO_SWITCH::~RADIO_SWITCH()");
20
973
}
21
22
void RADIO_SWITCH::on()
23
12
{
24
12
    main433MHz.sendCode(RADIO_EQ::m_config.onCode);
25
12
    m_state = STATE::ON;
26
12
    RADIO_EQ::m_my_data->main_iDomStatus->setObjectState(RADIO_EQ::m_config.name, STATE::ON);
27
12
}
28
29
void RADIO_SWITCH::off()
30
15
{
31
15
    main433MHz.sendCode(RADIO_EQ::m_config.offCode);
32
15
    m_state = STATE::OFF;
33
15
    RADIO_EQ::m_my_data->main_iDomStatus->setObjectState(RADIO_EQ::m_config.name,STATE::OFF);
34
15
}
35
36
void RADIO_SWITCH::onFor15sec()
37
1
{
38
1
    main433MHz.sendCode(RADIO_EQ::m_config.on15sec);
39
1
    m_state = STATE::WORKING;
40
1
}
41
42
void RADIO_SWITCH::onSunrise()
43
10
{
44
10
    if(m_sunrise == STATE::ON ){
45
1
        on();
46
1
        m_my_data->myEventHandler.run("iDom")->addEvent("radio switch "+RADIO_EQ::m_config.name + " ON due to sunrise");
47
1
    }
48
9
    else if(m_sunrise == STATE::OFF){
49
3
        off();
50
3
        m_my_data->myEventHandler.run("iDom")->addEvent("radio switch "+RADIO_EQ::m_config.name + " OFF due to sunrise");
51
3
    }
52
10
}
53
54
void RADIO_SWITCH::onSunset()
55
11
{
56
11
    if(m_sunset == STATE::ON ){
57
3
        on();
58
3
        m_my_data->myEventHandler.run("iDom")->addEvent("radio switch "+RADIO_EQ::m_config.name + " ON due to sunset");
59
3
    }
60
8
    else if(m_sunset == STATE::OFF){
61
1
        off();
62
1
        m_my_data->myEventHandler.run("iDom")->addEvent("radio switch "+RADIO_EQ::m_config.name + " OFF due to sunset");
63
1
    }
64
11
}
65
66
void RADIO_SWITCH::onLockHome()
67
7
{
68
7
    if (m_config.lock == "ON")
69
1
    {
70
1
        on();
71
1
        m_my_data->myEventHandler.run("iDom")->addEvent("radio switch "+RADIO_EQ::m_config.name + " ON due to 433MHz button pressed");
72
1
    }
73
6
    else if(m_config.lock == "OFF")
74
2
    {
75
2
        off();
76
2
        m_my_data->myEventHandler.run("iDom")->addEvent("radio switch "+RADIO_EQ::m_config.name + " OFF due to 433MHz button pressed");
77
2
    }
78
7
}
79
80
void RADIO_SWITCH::onUnlockHome()
81
7
{
82
7
    if (m_config.unlock == "ON")
83
2
    {
84
2
        on();
85
2
        m_my_data->myEventHandler.run("iDom")->addEvent("radio switch "+RADIO_EQ::m_config.name + " ON due to 433MHz button pressed");
86
2
    }
87
5
    else if (m_config.unlock == "OFF")
88
1
    {
89
1
        off();
90
1
        m_my_data->myEventHandler.run("iDom")->addEvent("radio switch "+RADIO_EQ::m_config.name + " OFF due to 433MHz button pressed");
91
1
    }
92
7
}
93
94
STATE RADIO_SWITCH::getState()
95
365
{
96
365
    return m_state;
97
365
}
98
99
std::string RADIO_SWITCH::getName()
100
521
{
101
521
    return RADIO_EQ::m_config.name;
102
521
}
103
104
std::string RADIO_SWITCH::getID()
105
110
{
106
110
    return RADIO_EQ::m_config.ID;
107
110
}
108
109
void RADIO_SWITCH::setCode(RADIO_EQ_CONFIG cfg)
110
977
{
111
977
    RADIO_EQ::m_config.onCode = cfg.onCode;
112
977
    RADIO_EQ::m_config.offCode = cfg.offCode;
113
977
    RADIO_EQ::m_config.on15sec = cfg.on15sec;
114
977
    RADIO_EQ::m_config.type = cfg.type;
115
977
    RADIO_EQ::m_config.lock = cfg.lock;
116
977
    RADIO_EQ::m_config.unlock = cfg.unlock;
117
977
    RADIO_EQ::m_config.name = cfg.name;
118
977
119
977
    if(cfg.sunset == "on"){
120
2
        m_sunset = STATE::ON;
121
2
    }
122
977
    if(cfg.sunset == "off"){
123
1
        m_sunset = STATE::OFF;
124
1
    }
125
977
    if(cfg.sunrise == "on"){
126
1
        m_sunrise = STATE::ON;
127
1
    }
128
977
    if(cfg.sunrise == "off"){
129
2
        m_sunrise = STATE::OFF;
130
2
    }
131
977
}
132
133
RADIO_EQ_CONTAINER::RADIO_EQ_CONTAINER(thread_data *my_data)
134
194
{
135
194
    puts("RADIO_EQ_CONTAINER::RADIO_EQ_CONTAINER()");
136
194
    this->my_data = my_data;
137
194
}
138
139
RADIO_EQ_CONTAINER::~RADIO_EQ_CONTAINER()
140
194
{
141
1.55k
    for(auto it = m_radioEqMap.begin(); it != m_radioEqMap.end(); ++it) {
142
1.35k
        delete it->second;
143
1.35k
    }
144
194
    puts("RADIO_EQ_CONTAINER::~RADIO_EQ_CONTAINER()");
145
194
}
146
147
void RADIO_EQ_CONTAINER::addRadioEq( RADIO_EQ_CONFIG cfg, RADIO_EQ_TYPE type)
148
1.36k
{
149
1.36k
    switch (type) {
150
1.36k
    case RADIO_EQ_TYPE::SWITCH:
151
973
        m_radioEqMap.insert(std::make_pair(cfg.name, new RADIO_SWITCH(my_data, cfg, RADIO_EQ_TYPE::SWITCH) ) );
152
973
        break;
153
1.36k
    case RADIO_EQ_TYPE::BUTTON:
154
195
        m_radioEqMap.insert(std::make_pair(cfg.name, new RADIO_BUTTON(my_data, cfg, RADIO_EQ_TYPE::BUTTON) ) );
155
195
        break;
156
1.36k
    case RADIO_EQ_TYPE::WEATHER_S:
157
193
        m_radioEqMap.insert(std::make_pair(cfg.name, new RADIO_WEATHER_STATION(my_data, cfg, RADIO_EQ_TYPE::WEATHER_S) ) );
158
193
        break;
159
1.36k
    default:
160
1
        break;
161
1.36k
    }
162
1.36k
}
163
164
void RADIO_EQ_CONTAINER::addRadioEq(RADIO_EQ_CONFIG cfg, const std::string& type)
165
6
{
166
6
    RADIO_EQ_TYPE ret = RADIO_EQ_TYPE::NONE;
167
6
    if(type == "SWITCH") ret = RADIO_EQ_TYPE::SWITCH;
168
3
    else if(type == "BUTTON") ret = RADIO_EQ_TYPE::BUTTON;
169
2
    else if(type == "WEATHER") ret = RADIO_EQ_TYPE::WEATHER_S;
170
2
    else if(type == "PIR") ret = RADIO_EQ_TYPE::PIR;
171
1
    else if(type == "GATE") ret = RADIO_EQ_TYPE::GATE;
172
1
    else throw WRONG_FORMAT();
173
5
    std::cout << " id ma : " << cfg.ID << std::endl;
174
5
    std::stoi(cfg.ID); //check ID is number
175
5
    addRadioEq(cfg,ret);
176
5
}
177
178
void RADIO_EQ_CONTAINER::deleteRadioEq(const std::string& name)
179
4
{
180
4
    delete m_radioEqMap[name];
181
4
    m_radioEqMap.erase(name);
182
4
    saveConfig(my_data->server_settings->radio433MHzConfigFile);
183
4
}
184
185
RADIO_EQ* RADIO_EQ_CONTAINER::getEqPointer(std::string name)
186
1.04k
{
187
1.04k
    auto m = m_radioEqMap.find(name);
188
1.04k
    if (m != m_radioEqMap.end()){
189
1.04k
        return (m->second);
190
1.04k
    }
191
2
    else
192
2
    {
193
2
        throw std::string("433MHz equipment not found "+name);
194
2
    }
195
0
}
196
197
std::vector<RADIO_SWITCH*> RADIO_EQ_CONTAINER::getSwitchPointerVector()
198
92
{
199
92
    std::vector<RADIO_SWITCH*> switchVector;
200
92
201
648
    for (auto it : m_radioEqMap){
202
648
        if (it.second->getType() == RADIO_EQ_TYPE::SWITCH){
203
463
            switchVector.push_back(static_cast<RADIO_SWITCH*>(it.second));
204
463
        }
205
648
    }
206
92
    return switchVector;
207
92
}
208
209
std::vector<RADIO_BUTTON *> RADIO_EQ_CONTAINER::getButtonPointerVector()
210
226
{
211
226
    std::vector<RADIO_BUTTON*> buttonVector;
212
226
213
1.58k
    for (auto it : m_radioEqMap){
214
1.58k
        if (it.second->getType() == RADIO_EQ_TYPE::BUTTON){
215
228
            buttonVector.push_back(static_cast<RADIO_BUTTON*>(it.second));
216
228
        }
217
1.58k
    }
218
226
    return buttonVector;
219
226
}
220
221
std::vector<RADIO_WEATHER_STATION *> RADIO_EQ_CONTAINER::getWeather_StationPtrVector()
222
30
{
223
30
    std::vector<RADIO_WEATHER_STATION*> weatherStVe;
224
212
    for (auto it : m_radioEqMap){
225
212
        if (it.second->getType() == RADIO_EQ_TYPE::WEATHER_S){
226
30
            weatherStVe.push_back(static_cast<RADIO_WEATHER_STATION*>(it.second));
227
30
        }
228
212
    }
229
30
    return weatherStVe;
230
30
}
231
232
std::string RADIO_EQ_CONTAINER::listAllName()
233
22
{
234
22
    std::string allName;
235
22
236
177
    for(auto it = m_radioEqMap.begin(); it != m_radioEqMap.end(); ++it) {
237
155
        allName.append(it->first);
238
155
        allName.append("\t ID: ");
239
155
        allName.append( it->second->getID() );
240
155
        allName.append("\t state: ");
241
155
        allName.append(stateToString(it->second->getState() ));
242
155
        allName.append("\n");
243
155
    }
244
22
245
22
    return allName;
246
22
}
247
248
bool RADIO_EQ_CONTAINER::nameExist(const std::string& name)
249
14
{
250
14
    bool exist = false;
251
14
    if(m_radioEqMap.find(name) != m_radioEqMap.end())
252
5
    {
253
5
        exist = true;
254
5
    }
255
14
    return exist;
256
14
}
257
258
void RADIO_EQ_CONTAINER::loadConfig(const std::string& filePath)
259
194
{
260
194
    std::ifstream myfile (filePath);
261
194
    if (myfile.is_open())
262
194
    {
263
194
        m_radioEqMap.clear();
264
194
        nlohmann::json j;
265
194
        myfile >> j;
266
194
267
194
        RADIO_EQ_CONFIG cfg;
268
194
269
194
        try
270
194
        {
271
194
            nlohmann::json switchJson = j.at("SWITCH");
272
1.16k
            for (nlohmann::json::iterator it = switchJson.begin(); it != switchJson.end(); ++it)
273
970
            {
274
970
                nlohmann::json switchJson = it.value();
275
970
                cfg.name = switchJson.at("name").get<std::string>();
276
970
                cfg.ID   = switchJson.at("id").get<std::string>();
277
970
                cfg.offCode = switchJson.at("OFF").get<std::string>();
278
970
                cfg.onCode  = switchJson.at("ON").get<std::string>();
279
970
                cfg.on15sec = switchJson.at("on15sec").get<std::string>();
280
970
                cfg.sunrise = switchJson.at("sunrise").get<std::string>();
281
970
                cfg.sunset  = switchJson.at("sunset").get<std::string>();
282
970
                cfg.lock    = switchJson.at("lock").get<std::string>();
283
970
                cfg.unlock  = switchJson.at("unlock").get<std::string>();
284
970
                cfg.type    = switchJson.at("type").get<std::string>();
285
970
                addRadioEq(cfg,RADIO_EQ_TYPE::SWITCH);
286
970
                dynamic_cast<RADIO_SWITCH*>(getEqPointer(cfg.name))->setCode(cfg);
287
970
            }
288
194
        }
289
194
        catch(...)
290
194
        {
291
0
        log_file_mutex.mutex_lock();
292
0
        log_file_cout << DEBUG << "no SWITCH equipment in config" << std::endl;
293
0
        log_file_mutex.mutex_unlock();
294
0
        }
295
194
        try
296
194
        {
297
194
            nlohmann::json buttonJson = j.at("BUTTON");
298
388
            for (nlohmann::json::iterator it = buttonJson.begin(); it != buttonJson.end(); ++it)
299
194
            {
300
194
                nlohmann::json buttonJson = it.value();
301
194
                cfg.name = buttonJson.at("name").get<std::string>();
302
194
                cfg.ID   = buttonJson.at("id").get<std::string>();
303
194
                cfg.offCode = buttonJson.at("OFF").get<std::string>();
304
194
                cfg.onCode  = buttonJson.at("ON").get<std::string>();
305
194
                cfg.type    = buttonJson.at("type").get<std::string>();
306
194
                addRadioEq(cfg,RADIO_EQ_TYPE::BUTTON);
307
194
            }
308
194
        }
309
194
        catch(...)
310
194
        {
311
0
            log_file_mutex.mutex_lock();
312
0
            log_file_cout << DEBUG << "no BUTTONs equipment in config" << std::endl;
313
0
            log_file_mutex.mutex_unlock();
314
0
#ifdef BT_TEST
315
0
            std::cout << "no BUTTONs equipment in config" <<std::endl;
316
0
#endif
317
0
        }
318
194
319
194
        try
320
194
        {
321
194
            nlohmann::json weatherJson= j.at("WEATHER");
322
387
            for (nlohmann::json::iterator it = weatherJson.begin(); it != weatherJson.end(); ++it)
323
193
            {
324
193
                nlohmann::json weatherJson = it.value();
325
193
                cfg.name = weatherJson.at("name").get<std::string>();
326
193
                cfg.ID   = weatherJson.at("id").get<std::string>();
327
193
                cfg.type    = weatherJson.at("type").get<std::string>();
328
193
                addRadioEq(cfg,RADIO_EQ_TYPE::WEATHER_S);
329
193
            }
330
194
        }
331
194
        catch(...)
332
194
        {
333
1
            log_file_mutex.mutex_lock();
334
1
            log_file_cout << DEBUG << "no WEATHER STAIONs equipment in config" << std::endl;
335
1
            log_file_mutex.mutex_unlock();
336
1
#ifdef BT_TEST
337
1
            std::cout << "no WEATHER STAIONs equipment in config" <<std::endl;
338
1
#endif
339
1
        }
340
194
341
194
        myfile.close();
342
194
    }
343
0
    else std::cout << "Unable to open file";
344
194
}
345
346
void RADIO_EQ_CONTAINER::saveConfig(const std::string& filePath)
347
10
{
348
10
    nlohmann::json switchJson;
349
10
    nlohmann::json buttonJson;
350
10
    nlohmann::json weatherJson;
351
10
352
10
    std::vector<RADIO_SWITCH*> vSwitch = getSwitchPointerVector();
353
10
    for(auto s : vSwitch)
354
51
    {
355
51
        switchJson[s->getName()] = s->m_config.getJson();
356
51
    }
357
10
358
10
    std::vector<RADIO_BUTTON*> vButton = getButtonPointerVector();
359
10
    for (auto s : vButton)
360
11
    {
361
11
        buttonJson[s->getName()] = s->m_config.getJson();
362
11
    }
363
10
364
10
    std::vector<RADIO_WEATHER_STATION *> vWeather = getWeather_StationPtrVector();
365
10
    for(auto s : vWeather)
366
10
    {
367
10
        weatherJson[s->getName()] = s->m_config.getJson();
368
10
    }
369
10
370
10
    m_configJson["SWITCH"] = switchJson;
371
10
    m_configJson["BUTTON"] = buttonJson;
372
10
    m_configJson["WEATHER"] = weatherJson;
373
10
    // write prettified JSON to another file
374
10
    std::ofstream o(filePath);
375
10
    o << std::setw(4) << m_configJson << std::endl;
376
10
}
377
378
RADIO_EQ::RADIO_EQ()
379
1.36k
{
380
1.36k
    this->m_my_data = std::nullptr_t();
381
1.36k
    puts("RADIO_EQ::RADIO_EQ()");
382
1.36k
}
383
384
RADIO_EQ::~RADIO_EQ()
385
1.36k
{
386
1.36k
    puts("RADIO_EQ::~RADIO_EQ()");
387
1.36k
}
388
389
RADIO_EQ_TYPE RADIO_EQ::getType()
390
2.44k
{
391
2.44k
    return m_type;
392
2.44k
}
393
394
RADIO_WEATHER_STATION::RADIO_WEATHER_STATION(thread_data *my_data, const RADIO_EQ_CONFIG& cfg, RADIO_EQ_TYPE type)
395
193
{
396
193
    puts("RADIO_WEATHER_STATION::RADIO_WEATHER_STATION()");
397
193
    RADIO_EQ::m_my_data = my_data;
398
193
    RADIO_EQ::m_type = type;
399
193
    RADIO_EQ::m_config = cfg;
400
193
}
401
402
RADIO_WEATHER_STATION::~RADIO_WEATHER_STATION()
403
193
{
404
193
    puts("RADIO_WEATHER_STATION::~RADIO_WEATHER_STATION()");
405
193
}
406
407
STATE RADIO_WEATHER_STATION::getState()
408
22
{
409
22
    return m_state;
410
22
}
411
412
std::string RADIO_WEATHER_STATION::getName()
413
10
{
414
10
    return RADIO_EQ::m_config.name;
415
10
}
416
417
std::string RADIO_WEATHER_STATION::getID()
418
34
{
419
34
    return RADIO_EQ::m_config.ID;
420
34
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDom_server_OOP.h
Line
Count
Source
1
#ifndef GLOBAL_H
2
#define GLOBAL_H
3
4
#include <iostream>
5
#include <fstream>
6
#include <string>
7
#include <cstdlib>
8
#include <pthread.h>
9
#include <stdio.h>
10
#include <stdlib.h>
11
#include <sys/socket.h>
12
#include <sys/types.h>
13
#include <netinet/in.h>
14
#include <vector>
15
#include <thread>
16
#include <arpa/inet.h>
17
#include <netinet/in.h>
18
#include <unistd.h>
19
#include <sys/fcntl.h>
20
#include <unistd.h>
21
#include <errno.h>
22
#include <signal.h>
23
#include <time.h>
24
#include <wiringPi.h>
25
#include <chrono>
26
#include <array>
27
28
// MOJE BIBLIOTEKI
29
#include "KEY/key.h"
30
#include "logger/logger.hpp"
31
#include "files_tree/files_tree.h"
32
#include "menu_tree/menu_tree.h"
33
#include "LCD_c/lcd_c.h"
34
#include "command/command.h"
35
#include "../libs/event_counters/event_counters_handler.h"
36
#include "iDomTools/idomtools.h"
37
#include "iDomStatus/idomstatus.h"
38
#include "iDomSaveState/idom_save_state.h"
39
40
4
#define log_file_cout  f_log //std::cout zmien f_log na std::cout i bedzie wypisywac na ekran
41
2
#define log_file_mutex f_log
42
43
enum class iDomStateEnum{
44
    CLOSE = 0,
45
    RELOAD,
46
    ERROR,
47
    WORKING,
48
    HARD_RELOAD
49
};
50
51
namespace iDomConst
52
{
53
constexpr int MAX_CONNECTION = 10;
54
constexpr int FREE  = 1;
55
constexpr int RS232 = 11;
56
constexpr int CLOCK = 12;
57
constexpr int ok    = 0;
58
constexpr int GPIO_SPIK = 21;
59
constexpr int GPIO_PRINTER = 22;
60
constexpr int BUTTON_PIN = 25;
61
}
62
struct ALERT
63
{
64
    Clock time;
65
    STATE state = STATE::DEACTIVE;
66
    unsigned int fromVolume = 48;
67
    unsigned int toVolume = 58;
68
    unsigned int radioID = 8;
69
};
70
71
extern std::string _logfile;
72
extern Logger log_file_mutex;
73
extern std::string buffer;
74
75
enum class TEMPERATURE_STATE;
76
enum class PILOT_KEY;
77
78
struct MPD_info{
79
    std::string title   = "NULL";
80
    std::string radio   = "NULL";
81
    std::string artist  = "NULL";
82
    int volume = 0;
83
    bool isPlay = false;
84
    int currentSongID = 0;
85
    std::vector <std::string> songList = {"NULL"};
86
};
87
struct s_pointer{
88
    unsigned int *ptr_who;
89
    int32_t *ptr_buf;
90
};
91
92
struct Thread_array_struc {
93
    std::thread thread;
94
    std::thread::id thread_ID = std::thread::id(0);
95
    std::string thread_name;
96
    int thread_socket = 0;
97
};
98
99
struct address_another_servers {
100
    int id;
101
    std::string SERVER_IP;
102
};
103
104
struct FTP_SERVER{
105
    std::string URL;
106
    std::string user;
107
    std::string pass;
108
};
109
struct iDOM_STATE{
110
    STATE houseState = STATE::UNDEFINE;
111
112
};
113
114
struct config{
115
    std::string portRS232;
116
    std::string portRS232_clock;
117
    std::string BaudRate;
118
    std::string RFLinkPort;
119
    std::string RFLinkBaudRate;
120
    int PORT;
121
    std::string SERVER_IP;
122
    std::string MPD_IP;
123
    std::string MOVIES_DB_PATH;
124
    std::string MENU_PATH;
125
    std::string THREAD_MPD   = "NULL";
126
    std::string THREAD_IRDA  = "NULL";
127
    std::string THREAD_CRON  = "NULL";
128
    std::string THREAD_RS232 = "NULL";
129
    std::string THREAD_DUMMY = "NULL";
130
    std::string TS_KEY= " gg ";
131
    std::string cameraLedON = "";
132
    std::string cameraLedOFF ="";
133
    std::string cameraURL="";
134
    std::string facebookAccessToken = "";
135
    std::string viberToken = "NULL";
136
    std::string viberAvatar;
137
    std::vector <std::string> viberReceiver;
138
    std::string viberSender;
139
    std::string radio433MHzConfigFile;
140
    std::string omxplayerFile = "NULL";
141
    int ID_server = 0;
142
    int v_delay;
143
    bool encrypted = true;
144
145
    FTP_SERVER ftpServer;
146
    std::string lightningApiURL = "NULL";
147
    std::string saveFilePath = "NULL";
148
};
149
150
struct LED_Strip{
151
    std::string from;
152
    std::string to;
153
    std::string R;
154
    std::string G;
155
    std::string B;
156
    std::string colorName;
157
158
    LED_Strip (int from, int to, int r, int g, int b, std::string colorName = "NULL"):from(std::to_string(from)),
159
        to(std::to_string(to)),
160
        R(std::to_string(r)),
161
        G(std::to_string(g)),
162
        B(std::to_string(b)),
163
        colorName(colorName)
164
    {
165
166
    }
167
    LED_Strip (const std::string& from,
168
               const std::string& to,
169
               const std::string& r,
170
               const std::string& g,
171
               const std::string& b,
172
               const std::string& colorName = "NULL"):
173
        from(from),
174
        to(to),
175
        R(r),
176
        G(g),
177
        B(b),
178
        colorName(colorName)
179
    {
180
181
    }
182
183
    void set (const std::string& from,
184
              const std::string& to,
185
              const std::string& r,
186
              const std::string& g,
187
              const std::string& b,
188
              const std::string& colorName = "NULL")
189
    {
190
        this->from =from;
191
        this->to = to;
192
        R = r;
193
        G = g;
194
        B = b;
195
        this->colorName =colorName;
196
    }
197
198
    void set (int from, int to, int r, int g, int b, std::string colorName = "NULL"){
199
        this->from = std::to_string(from);
200
        this->to = std::to_string(to);
201
        R = std::to_string(r);
202
        G = std::to_string(g);
203
        B = std::to_string(b);
204
        this->colorName =colorName;
205
    }
206
207
    std::string getColorName() const{
208
        return colorName;
209
    }
210
211
    std::string get(unsigned int _from, unsigned int _to) const{
212
        if (_from != 0 || _to != 60){
213
            return "LED:["+std::to_string(_from)+"-"+std::to_string(_to)+"-"+R+"-"+G+"-"+B+"];";
214
        }
215
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
216
    }
217
218
    std::string makeCommand(const std::string& from,
219
                            const std::string& to,
220
                            const std::string& R,
221
                            const std::string& G,
222
                            const std::string& B){
223
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
224
    }
225
};
226
227
struct pilot_led{
228
    unsigned int counter=0;
229
    std::vector<LED_Strip> colorLED   = { LED_Strip(1,60,237,145,33 ,"carrot orange"),
230
                                          LED_Strip(1,60,255,0,0    ,"red"),
231
                                          LED_Strip(1,60,0,255,0    ,"green"),
232
                                          LED_Strip(1,60,0,0,255    ,"blue"),
233
                                          LED_Strip(1,60,255,255,255,"white"),
234
                                          LED_Strip(1,60,255,255,0  ,"yellow"),
235
                                          LED_Strip(1,60,0,255,255  ,"cyan"),
236
                                          LED_Strip(1,60,255,0,255  ,"magenta")
237
                                        };
238
};
239
240
class command; // for struc thread_data req
241
class iDomTOOLS;
242
class RADIO_EQ_CONTAINER;
243
class RFLinkHandler;
244
245
struct thread_data{
246
    int s_client_sock;
247
    struct sockaddr_in from;
248
    struct config *server_settings = NULL;
249
    struct s_pointer pointer;
250
    LCD_c *mainLCD = NULL;
251
    files_tree *main_tree = NULL;
252
    menu_tree *main_MENU = NULL;
253
    iDomTOOLS *main_iDomTools = NULL;
254
    RFLinkHandler *main_RFLink = NULL;
255
    std::array<Thread_array_struc, iDomConst::MAX_CONNECTION> *main_THREAD_arr = NULL;
256
    time_t start;
257
    time_t now_time;
258
    int sleeper;
259
    std::map <std::string, std::unique_ptr <KEY> > key_map;
260
    MPD_info *ptr_MPD_info = NULL;
261
    pilot_led * ptr_pilot_led = NULL;
262
    std::map <std::string, std::unique_ptr<command> >* commandMapPtr = NULL;
263
    event_counters_handler myEventHandler;
264
    std::string encriptionKey = "40%";
265
    iDomSTATUS *main_iDomStatus;
266
    iDOM_STATE idom_all_state;
267
    ALERT alarmTime;
268
    std::shared_ptr<RADIO_EQ_CONTAINER> main_REC;
269
    iDomStateEnum iDomProgramState = iDomStateEnum::WORKING;
270
};
271
272
struct thread_data_rs232{
273
    std::string portRS232;
274
    std::string portRS232_clock;
275
    std::string BaudRate;
276
    struct s_pointer pointer;
277
};
278
279
#endif // GLOBAL_H
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/RADIO_433_eq/radio_433_eq.h
Line
Count
Source (jump to first uncovered line)
1
#ifndef RADIO_SWITCH_H
2
#define RADIO_SWITCH_H
3
#include <gtest/gtest.h>
4
#include <gmock/gmock.h>
5
#include <map>
6
#include "../iDomStatus/idomstatus.h"
7
#include "../433MHz/RFLink/rflinkhandler.h"
8
9
#include "../433MHz/rc_433mhz.h"
10
#include "json.hpp"
11
12
struct WEATHER_STRUCT{
13
private:
14
    unsigned long int m_counter = 0;
15
protected:
16
    unsigned int m_humidity = 0;
17
    double m_temperature = 0.0;
18
    unsigned int m_barometricPressure = 0;
19
public:
20
4
    unsigned int getHumidity(){ return m_humidity; }
21
7
    double getTemperature(){ return m_temperature; }
22
3
    unsigned int getBarometricPressure(){ return m_barometricPressure; }
23
2
    std::string getDataString(){
24
2
        return "data: "+std::to_string(m_counter)+"\n"+"Humidity=" + std::to_string(getHumidity()) +"%\n"+
25
2
                "temperature= " + to_string_with_precision(getTemperature()) + "c\n"+
26
2
                "Pressure= " + std::to_string(getBarometricPressure())+ "kPa\n";
27
2
    }
28
29
5
    void putData(std::string data){
30
5
        std::string tempStr;
31
5
        int t = 0;
32
5
        ++m_counter;
33
5
        try{
34
5
            m_humidity = std::stoi( RFLinkHandler::getArgumentValueFromRFLinkMSG(data, "HUM") );
35
5
        }
36
5
        catch (...){ }
37
5
        try{
38
5
            m_barometricPressure = std::stoi( RFLinkHandler::getArgumentValueFromRFLinkMSG(data, "BARO") );
39
5
        }
40
5
        catch (...){ }
41
5
        try{
42
5
            tempStr = RFLinkHandler::getArgumentValueFromRFLinkMSG(data, "TEMP");
43
5
            std::stringstream ss;
44
5
            ss << std::hex << tempStr.substr(tempStr.size()-3,tempStr.size());
45
5
            ss >> t;
46
5
            m_temperature = t / 10.0;
47
5
            if(tempStr.at(0) == '8'){
48
2
                m_temperature *= -1.0;
49
2
            }
50
5
        }
51
5
        catch (...){ }
52
5
        //std::cout << "DUPA: "<<data<<" temp=" << m_temperature<< " hum="<<m_humidity<< std::endl;
53
5
    }
54
};
55
56
enum class RADIO_EQ_TYPE{
57
    SWITCH = 1,
58
    PIR,
59
    GATE,
60
    BUTTON,
61
    WEATHER_S,
62
    NONE
63
};
64
struct RADIO_EQ_CONFIG{
65
    std::string name = "NULL";
66
    std::string ID   = "NULL";
67
    std::string type = "NULL";
68
    std::string onCode  = "NULL";
69
    std::string offCode = "NULL";
70
    std::string on15sec = "NULL";
71
    std::string sunrise = "NULL";
72
    std::string sunset  = "NULL";
73
    std::string lock   = "NULL";
74
    std::string unlock = "NULL";
75
    void set(std::string type,
76
             std::string name,
77
             std::string ID,
78
             std::string onCode = "null",
79
             std::string offCode = "null",
80
             std::string on15sec = "null",
81
             std::string sunrise = "null",
82
             std::string sunset = "null",
83
             std::string lock = "null",
84
6
             std::string unlock = "null"){
85
6
        this->name = name;
86
6
        this->ID   = ID;
87
6
        this->type = type;
88
6
        this->onCode  = onCode;
89
6
        this->offCode = offCode;
90
6
        this->on15sec = on15sec;
91
6
        this->sunrise = sunrise;
92
6
        this->sunset  = sunset;
93
6
        this->lock   = lock;
94
6
        this->unlock = unlock;
95
6
    }
96
97
72
    nlohmann::json getJson(){
98
72
        nlohmann::json jj;
99
72
        jj["name"]  = name;
100
72
        jj["id"]    = ID;
101
72
        jj["type"]  = type;
102
72
        jj["ON"]    = onCode;
103
72
        jj["OFF"]   = offCode;
104
72
        jj["on15sec"] = on15sec;
105
72
        jj["sunrise"] = sunrise;
106
72
        jj["sunset"]  = sunset;
107
72
        jj["lock"]   = lock;
108
72
        jj["unlock"] = unlock;
109
72
        return jj;
110
72
    }
111
};
112
113
class RADIO_EQ{
114
public:
115
    RADIO_EQ();
116
    virtual ~RADIO_EQ();
117
    virtual STATE getState() = 0;
118
    virtual std::string getName() = 0;
119
    virtual std::string getID() = 0;
120
    virtual RADIO_EQ_TYPE getType();
121
protected:
122
    thread_data *m_my_data;
123
    RADIO_EQ_TYPE m_type;
124
public:
125
    RADIO_EQ_CONFIG m_config;
126
};
127
class RADIO_WEATHER_STATION: public RADIO_EQ
128
{
129
    STATE m_state = STATE::UNDEFINE;
130
131
public:
132
    RADIO_WEATHER_STATION(thread_data * my_data, const RADIO_EQ_CONFIG& cfg, RADIO_EQ_TYPE type);
133
    ~RADIO_WEATHER_STATION();
134
    STATE getState();
135
    std::string getName();
136
    std::string getID();
137
    // data
138
    WEATHER_STRUCT data;
139
};
140
class RADIO_BUTTON: public RADIO_EQ
141
{
142
    STATE m_state = STATE::UNDEFINE;
143
144
public:
145
    RADIO_BUTTON(thread_data * my_data, const RADIO_EQ_CONFIG& cfg, RADIO_EQ_TYPE type);
146
    ~RADIO_BUTTON();
147
    STATE getState();
148
    void setState(STATE s);
149
    std::string getName();
150
    std::string getID();
151
};
152
153
class RADIO_SWITCH: public RADIO_EQ
154
{
155
#ifdef BT_TEST
156
public:
157
#endif
158
    RC_433MHz main433MHz;
159
    STATE m_state = STATE::UNDEFINE;
160
public:
161
    RADIO_SWITCH(thread_data * my_data, const RADIO_EQ_CONFIG& cfg, RADIO_EQ_TYPE type);
162
    ~RADIO_SWITCH();
163
    void on();
164
    void off();
165
    void onFor15sec();
166
    void onSunrise();
167
    void onSunset();
168
    void onLockHome();
169
    void onUnlockHome();
170
    STATE getState();
171
    std::string getName();
172
    std::string getID();
173
    void setCode(RADIO_EQ_CONFIG cfg);
174
    STATE m_sunrise = STATE::UNDEFINE;
175
    STATE m_sunset  = STATE::UNDEFINE;
176
};
177
178
class RADIO_EQ_CONTAINER
179
{
180
    std::map <std::string, RADIO_EQ* > m_radioEqMap;
181
    thread_data * my_data;
182
    nlohmann::json m_configJson;
183
public:
184
    RADIO_EQ_CONTAINER(thread_data * my_data);
185
    virtual ~RADIO_EQ_CONTAINER();
186
    void addRadioEq(RADIO_EQ_CONFIG cfg, RADIO_EQ_TYPE type);
187
    void addRadioEq(RADIO_EQ_CONFIG cfg, const std::string& type);
188
    void deleteRadioEq(const std::string &name);
189
    virtual RADIO_EQ* getEqPointer(std::string name);
190
    std::vector<RADIO_SWITCH*> getSwitchPointerVector();
191
    std::vector<RADIO_BUTTON*> getButtonPointerVector();
192
    std::vector<RADIO_WEATHER_STATION *> getWeather_StationPtrVector();
193
    std::string listAllName();
194
    bool nameExist(const std::string &name);
195
    void loadConfig(const std::string &filePath);
196
    void saveConfig(const std::string &filePath);
197
};
198
199
class RADIO_EQ_CONTAINER_STUB : public RADIO_EQ_CONTAINER
200
{
201
    thread_data * k;
202
public:
203
0
    RADIO_EQ_CONTAINER_STUB(thread_data * k):RADIO_EQ_CONTAINER(k){this->k = k;}
204
205
0
    virtual ~RADIO_EQ_CONTAINER_STUB(){puts("~RADIO_EQ_CONTAINER_STUB()");}
206
    MOCK_METHOD1(getEqPointer, RADIO_EQ*(std::string name));
207
};
208
209
#endif // RADIO_SWITCH_H
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/RADIO_433_eq/radio_433_eq.cpp
Line
Count
Source (jump to first uncovered line)
1
#include <iostream>
2
#include <fstream>
3
#include <sstream>
4
#include "radio_433_eq.h"
5
6
RADIO_SWITCH::RADIO_SWITCH(thread_data *my_data, const RADIO_EQ_CONFIG &cfg, RADIO_EQ_TYPE type):
7
    main433MHz(my_data)
8
973
{
9
973
    puts("RADIO_SWITCH::RADIO_SWITCH()");
10
973
    RADIO_EQ::m_my_data = my_data;
11
973
    RADIO_EQ::m_type = type;
12
973
    RADIO_EQ::m_config = cfg;
13
973
    m_sunrise = stringToState(cfg.sunrise);
14
973
    m_sunset  = stringToState(cfg.sunset);
15
973
}
16
17
RADIO_SWITCH::~RADIO_SWITCH()
18
973
{
19
973
    puts("RADIO_SWITCH::~RADIO_SWITCH()");
20
973
}
21
22
void RADIO_SWITCH::on()
23
12
{
24
12
    main433MHz.sendCode(RADIO_EQ::m_config.onCode);
25
12
    m_state = STATE::ON;
26
12
    RADIO_EQ::m_my_data->main_iDomStatus->setObjectState(RADIO_EQ::m_config.name, STATE::ON);
27
12
}
28
29
void RADIO_SWITCH::off()
30
15
{
31
15
    main433MHz.sendCode(RADIO_EQ::m_config.offCode);
32
15
    m_state = STATE::OFF;
33
15
    RADIO_EQ::m_my_data->main_iDomStatus->setObjectState(RADIO_EQ::m_config.name,STATE::OFF);
34
15
}
35
36
void RADIO_SWITCH::onFor15sec()
37
1
{
38
1
    main433MHz.sendCode(RADIO_EQ::m_config.on15sec);
39
1
    m_state = STATE::WORKING;
40
1
}
41
42
void RADIO_SWITCH::onSunrise()
43
10
{
44
10
    if(m_sunrise == STATE::ON ){
45
1
        on();
46
1
        m_my_data->myEventHandler.run("iDom")->addEvent("radio switch "+RADIO_EQ::m_config.name + " ON due to sunrise");
47
1
    }
48
10
    else if(m_sunrise == STATE::OFF){
49
3
        off();
50
3
        m_my_data->myEventHandler.run("iDom")->addEvent("radio switch "+RADIO_EQ::m_config.name + " OFF due to sunrise");
51
3
    }
52
10
}
53
54
void RADIO_SWITCH::onSunset()
55
11
{
56
11
    if(m_sunset == STATE::ON ){
57
3
        on();
58
3
        m_my_data->myEventHandler.run("iDom")->addEvent("radio switch "+RADIO_EQ::m_config.name + " ON due to sunset");
59
3
    }
60
11
    else if(m_sunset == STATE::OFF){
61
1
        off();
62
1
        m_my_data->myEventHandler.run("iDom")->addEvent("radio switch "+RADIO_EQ::m_config.name + " OFF due to sunset");
63
1
    }
64
11
}
65
66
void RADIO_SWITCH::onLockHome()
67
7
{
68
7
    if (m_config.lock == "ON")
69
7
    {
70
1
        on();
71
1
        m_my_data->myEventHandler.run("iDom")->addEvent("radio switch "+RADIO_EQ::m_config.name + " ON due to 433MHz button pressed");
72
1
    }
73
7
    else if(m_config.lock == "OFF")
74
6
    {
75
2
        off();
76
2
        m_my_data->myEventHandler.run("iDom")->addEvent("radio switch "+RADIO_EQ::m_config.name + " OFF due to 433MHz button pressed");
77
2
    }
78
7
}
79
80
void RADIO_SWITCH::onUnlockHome()
81
7
{
82
7
    if (m_config.unlock == "ON")
83
7
    {
84
2
        on();
85
2
        m_my_data->myEventHandler.run("iDom")->addEvent("radio switch "+RADIO_EQ::m_config.name + " ON due to 433MHz button pressed");
86
2
    }
87
7
    else if (m_config.unlock == "OFF")
88
5
    {
89
1
        off();
90
1
        m_my_data->myEventHandler.run("iDom")->addEvent("radio switch "+RADIO_EQ::m_config.name + " OFF due to 433MHz button pressed");
91
1
    }
92
7
}
93
94
STATE RADIO_SWITCH::getState()
95
365
{
96
365
    return m_state;
97
365
}
98
99
std::string RADIO_SWITCH::getName()
100
521
{
101
521
    return RADIO_EQ::m_config.name;
102
521
}
103
104
std::string RADIO_SWITCH::getID()
105
110
{
106
110
    return RADIO_EQ::m_config.ID;
107
110
}
108
109
void RADIO_SWITCH::setCode(RADIO_EQ_CONFIG cfg)
110
977
{
111
977
    RADIO_EQ::m_config.onCode = cfg.onCode;
112
977
    RADIO_EQ::m_config.offCode = cfg.offCode;
113
977
    RADIO_EQ::m_config.on15sec = cfg.on15sec;
114
977
    RADIO_EQ::m_config.type = cfg.type;
115
977
    RADIO_EQ::m_config.lock = cfg.lock;
116
977
    RADIO_EQ::m_config.unlock = cfg.unlock;
117
977
    RADIO_EQ::m_config.name = cfg.name;
118
977
119
977
    if(cfg.sunset == "on"){
120
2
        m_sunset = STATE::ON;
121
2
    }
122
977
    if(cfg.sunset == "off"){
123
1
        m_sunset = STATE::OFF;
124
1
    }
125
977
    if(cfg.sunrise == "on"){
126
1
        m_sunrise = STATE::ON;
127
1
    }
128
977
    if(cfg.sunrise == "off"){
129
2
        m_sunrise = STATE::OFF;
130
2
    }
131
977
}
132
133
RADIO_EQ_CONTAINER::RADIO_EQ_CONTAINER(thread_data *my_data)
134
194
{
135
194
    puts("RADIO_EQ_CONTAINER::RADIO_EQ_CONTAINER()");
136
194
    this->my_data = my_data;
137
194
}
138
139
RADIO_EQ_CONTAINER::~RADIO_EQ_CONTAINER()
140
194
{
141
1.55k
    for(auto it = m_radioEqMap.begin(); it != m_radioEqMap.end(); ++it) {
142
1.35k
        delete it->second;
143
1.35k
    }
144
194
    puts("RADIO_EQ_CONTAINER::~RADIO_EQ_CONTAINER()");
145
194
}
146
147
void RADIO_EQ_CONTAINER::addRadioEq( RADIO_EQ_CONFIG cfg, RADIO_EQ_TYPE type)
148
1.36k
{
149
1.36k
    switch (type) {
150
1.36k
    case RADIO_EQ_TYPE::SWITCH:
151
973
        m_radioEqMap.insert(std::make_pair(cfg.name, new RADIO_SWITCH(my_data, cfg, RADIO_EQ_TYPE::SWITCH) ) );
152
973
        break;
153
973
    case RADIO_EQ_TYPE::BUTTON:
154
195
        m_radioEqMap.insert(std::make_pair(cfg.name, new RADIO_BUTTON(my_data, cfg, RADIO_EQ_TYPE::BUTTON) ) );
155
195
        break;
156
973
    case RADIO_EQ_TYPE::WEATHER_S:
157
193
        m_radioEqMap.insert(std::make_pair(cfg.name, new RADIO_WEATHER_STATION(my_data, cfg, RADIO_EQ_TYPE::WEATHER_S) ) );
158
193
        break;
159
973
    default:
160
1
        break;
161
1.36k
    }
162
1.36k
}
163
164
void RADIO_EQ_CONTAINER::addRadioEq(RADIO_EQ_CONFIG cfg, const std::string& type)
165
6
{
166
6
    RADIO_EQ_TYPE ret = RADIO_EQ_TYPE::NONE;
167
6
    if(type == "SWITCH") ret = RADIO_EQ_TYPE::SWITCH;
168
6
    else if(type == "BUTTON") ret = RADIO_EQ_TYPE::BUTTON;
169
3
    else if(type == "WEATHER") ret = RADIO_EQ_TYPE::WEATHER_S;
170
2
    else if(type == "PIR") ret = RADIO_EQ_TYPE::PIR;
171
2
    else if(type == "GATE") ret = RADIO_EQ_TYPE::GATE;
172
1
    else throw WRONG_FORMAT();
173
6
    std::cout << " id ma : " << cfg.ID << std::endl;
174
5
    std::stoi(cfg.ID); //check ID is number
175
5
    addRadioEq(cfg,ret);
176
5
}
177
178
void RADIO_EQ_CONTAINER::deleteRadioEq(const std::string& name)
179
4
{
180
4
    delete m_radioEqMap[name];
181
4
    m_radioEqMap.erase(name);
182
4
    saveConfig(my_data->server_settings->radio433MHzConfigFile);
183
4
}
184
185
RADIO_EQ* RADIO_EQ_CONTAINER::getEqPointer(std::string name)
186
1.04k
{
187
1.04k
    auto m = m_radioEqMap.find(name);
188
1.04k
    if (m != m_radioEqMap.end()){
189
1.04k
        return (m->second);
190
1.04k
    }
191
1.04k
    else
192
1.04k
    {
193
2
        throw std::string("433MHz equipment not found "+name);
194
2
    }
195
1.04k
}
196
197
std::vector<RADIO_SWITCH*> RADIO_EQ_CONTAINER::getSwitchPointerVector()
198
92
{
199
92
    std::vector<RADIO_SWITCH*> switchVector;
200
92
201
648
    for (auto it : m_radioEqMap){
202
648
        if (it.second->getType() == RADIO_EQ_TYPE::SWITCH){
203
463
            switchVector.push_back(static_cast<RADIO_SWITCH*>(it.second));
204
463
        }
205
648
    }
206
92
    return switchVector;
207
92
}
208
209
std::vector<RADIO_BUTTON *> RADIO_EQ_CONTAINER::getButtonPointerVector()
210
226
{
211
226
    std::vector<RADIO_BUTTON*> buttonVector;
212
226
213
1.58k
    for (auto it : m_radioEqMap){
214
1.58k
        if (it.second->getType() == RADIO_EQ_TYPE::BUTTON){
215
228
            buttonVector.push_back(static_cast<RADIO_BUTTON*>(it.second));
216
228
        }
217
1.58k
    }
218
226
    return buttonVector;
219
226
}
220
221
std::vector<RADIO_WEATHER_STATION *> RADIO_EQ_CONTAINER::getWeather_StationPtrVector()
222
30
{
223
30
    std::vector<RADIO_WEATHER_STATION*> weatherStVe;
224
212
    for (auto it : m_radioEqMap){
225
212
        if (it.second->getType() == RADIO_EQ_TYPE::WEATHER_S){
226
30
            weatherStVe.push_back(static_cast<RADIO_WEATHER_STATION*>(it.second));
227
30
        }
228
212
    }
229
30
    return weatherStVe;
230
30
}
231
232
std::string RADIO_EQ_CONTAINER::listAllName()
233
22
{
234
22
    std::string allName;
235
22
236
177
    for(auto it = m_radioEqMap.begin(); it != m_radioEqMap.end(); ++it) {
237
155
        allName.append(it->first);
238
155
        allName.append("\t ID: ");
239
155
        allName.append( it->second->getID() );
240
155
        allName.append("\t state: ");
241
155
        allName.append(stateToString(it->second->getState() ));
242
155
        allName.append("\n");
243
155
    }
244
22
245
22
    return allName;
246
22
}
247
248
bool RADIO_EQ_CONTAINER::nameExist(const std::string& name)
249
14
{
250
14
    bool exist = false;
251
14
    if(m_radioEqMap.find(name) != m_radioEqMap.end())
252
14
    {
253
5
        exist = true;
254
5
    }
255
14
    return exist;
256
14
}
257
258
void RADIO_EQ_CONTAINER::loadConfig(const std::string& filePath)
259
194
{
260
194
    std::ifstream myfile (filePath);
261
194
    if (myfile.is_open())
262
194
    {
263
194
        m_radioEqMap.clear();
264
194
        nlohmann::json j;
265
194
        myfile >> j;
266
194
267
194
        RADIO_EQ_CONFIG cfg;
268
194
269
194
        try
270
194
        {
271
194
            nlohmann::json switchJson = j.at("SWITCH");
272
1.16k
            for (nlohmann::json::iterator it = switchJson.begin(); it != switchJson.end(); ++it)
273
970
            {
274
970
                nlohmann::json switchJson = it.value();
275
970
                cfg.name = switchJson.at("name").get<std::string>();
276
970
                cfg.ID   = switchJson.at("id").get<std::string>();
277
970
                cfg.offCode = switchJson.at("OFF").get<std::string>();
278
970
                cfg.onCode  = switchJson.at("ON").get<std::string>();
279
970
                cfg.on15sec = switchJson.at("on15sec").get<std::string>();
280
970
                cfg.sunrise = switchJson.at("sunrise").get<std::string>();
281
970
                cfg.sunset  = switchJson.at("sunset").get<std::string>();
282
970
                cfg.lock    = switchJson.at("lock").get<std::string>();
283
970
                cfg.unlock  = switchJson.at("unlock").get<std::string>();
284
970
                cfg.type    = switchJson.at("type").get<std::string>();
285
970
                addRadioEq(cfg,RADIO_EQ_TYPE::SWITCH);
286
970
                dynamic_cast<RADIO_SWITCH*>(getEqPointer(cfg.name))->setCode(cfg);
287
970
            }
288
194
        }
289
194
        catch(...)
290
194
        {
291
0
        log_file_mutex.mutex_lock();
292
0
        log_file_cout << DEBUG << "no SWITCH equipment in config" << std::endl;
293
0
        log_file_mutex.mutex_unlock();
294
0
        }
295
194
        try
296
194
        {
297
194
            nlohmann::json buttonJson = j.at("BUTTON");
298
388
            for (nlohmann::json::iterator it = buttonJson.begin(); it != buttonJson.end(); ++it)
299
194
            {
300
194
                nlohmann::json buttonJson = it.value();
301
194
                cfg.name = buttonJson.at("name").get<std::string>();
302
194
                cfg.ID   = buttonJson.at("id").get<std::string>();
303
194
                cfg.offCode = buttonJson.at("OFF").get<std::string>();
304
194
                cfg.onCode  = buttonJson.at("ON").get<std::string>();
305
194
                cfg.type    = buttonJson.at("type").get<std::string>();
306
194
                addRadioEq(cfg,RADIO_EQ_TYPE::BUTTON);
307
194
            }
308
194
        }
309
194
        catch(...)
310
194
        {
311
0
            log_file_mutex.mutex_lock();
312
0
            log_file_cout << DEBUG << "no BUTTONs equipment in config" << std::endl;
313
0
            log_file_mutex.mutex_unlock();
314
0
#ifdef BT_TEST
315
0
            std::cout << "no BUTTONs equipment in config" <<std::endl;
316
0
#endif
317
0
        }
318
194
319
194
        try
320
194
        {
321
194
            nlohmann::json weatherJson= j.at("WEATHER");
322
387
            for (nlohmann::json::iterator it = weatherJson.begin(); it != weatherJson.end(); ++it)
323
194
            {
324
193
                nlohmann::json weatherJson = it.value();
325
193
                cfg.name = weatherJson.at("name").get<std::string>();
326
193
                cfg.ID   = weatherJson.at("id").get<std::string>();
327
193
                cfg.type    = weatherJson.at("type").get<std::string>();
328
193
                addRadioEq(cfg,RADIO_EQ_TYPE::WEATHER_S);
329
193
            }
330
194
        }
331
194
        catch(...)
332
194
        {
333
1
            log_file_mutex.mutex_lock();
334
1
            log_file_cout << DEBUG << "no WEATHER STAIONs equipment in config" << std::endl;
335
1
            log_file_mutex.mutex_unlock();
336
1
#ifdef BT_TEST
337
1
            std::cout << "no WEATHER STAIONs equipment in config" <<std::endl;
338
1
#endif
339
1
        }
340
194
341
194
        myfile.close();
342
194
    }
343
194
    else std::cout << "Unable to open file";
344
194
}
345
346
void RADIO_EQ_CONTAINER::saveConfig(const std::string& filePath)
347
10
{
348
10
    nlohmann::json switchJson;
349
10
    nlohmann::json buttonJson;
350
10
    nlohmann::json weatherJson;
351
10
352
10
    std::vector<RADIO_SWITCH*> vSwitch = getSwitchPointerVector();
353
10
    for(auto s : vSwitch)
354
51
    {
355
51
        switchJson[s->getName()] = s->m_config.getJson();
356
51
    }
357
10
358
10
    std::vector<RADIO_BUTTON*> vButton = getButtonPointerVector();
359
10
    for (auto s : vButton)
360
11
    {
361
11
        buttonJson[s->getName()] = s->m_config.getJson();
362
11
    }
363
10
364
10
    std::vector<RADIO_WEATHER_STATION *> vWeather = getWeather_StationPtrVector();
365
10
    for(auto s : vWeather)
366
10
    {
367
10
        weatherJson[s->getName()] = s->m_config.getJson();
368
10
    }
369
10
370
10
    m_configJson["SWITCH"] = switchJson;
371
10
    m_configJson["BUTTON"] = buttonJson;
372
10
    m_configJson["WEATHER"] = weatherJson;
373
10
    // write prettified JSON to another file
374
10
    std::ofstream o(filePath);
375
10
    o << std::setw(4) << m_configJson << std::endl;
376
10
}
377
378
RADIO_EQ::RADIO_EQ()
379
1.36k
{
380
1.36k
    this->m_my_data = std::nullptr_t();
381
1.36k
    puts("RADIO_EQ::RADIO_EQ()");
382
1.36k
}
383
384
RADIO_EQ::~RADIO_EQ()
385
1.36k
{
386
1.36k
    puts("RADIO_EQ::~RADIO_EQ()");
387
1.36k
}
388
389
RADIO_EQ_TYPE RADIO_EQ::getType()
390
2.44k
{
391
2.44k
    return m_type;
392
2.44k
}
393
394
RADIO_WEATHER_STATION::RADIO_WEATHER_STATION(thread_data *my_data, const RADIO_EQ_CONFIG& cfg, RADIO_EQ_TYPE type)
395
193
{
396
193
    puts("RADIO_WEATHER_STATION::RADIO_WEATHER_STATION()");
397
193
    RADIO_EQ::m_my_data = my_data;
398
193
    RADIO_EQ::m_type = type;
399
193
    RADIO_EQ::m_config = cfg;
400
193
}
401
402
RADIO_WEATHER_STATION::~RADIO_WEATHER_STATION()
403
193
{
404
193
    puts("RADIO_WEATHER_STATION::~RADIO_WEATHER_STATION()");
405
193
}
406
407
STATE RADIO_WEATHER_STATION::getState()
408
22
{
409
22
    return m_state;
410
22
}
411
412
std::string RADIO_WEATHER_STATION::getName()
413
10
{
414
10
    return RADIO_EQ::m_config.name;
415
10
}
416
417
std::string RADIO_WEATHER_STATION::getID()
418
34
{
419
34
    return RADIO_EQ::m_config.ID;
420
34
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/RADIO_433_eq/radio_button.cpp
Line
Count
Source
1
#include "radio_433_eq.h"
2
/*
3
 * Najpierw możliwe do uzyskania funkcje załączania
4
5
    Załączenie chwilowe (momentary) - przekaźnik jest załączony tak długo jak długo naciskany jest klawisz pilota - nadawany kod
6
    Przełącznik (toggle) - przekaźnik jest załączany /wyłączany przy kolejnych naciśnięciach tego samego klawisza - nadajemy ten sam kod
7
    Włącz/wyłącz (latched) - przekaźnik jest załączany jednym kodem a wyłączany innym
8
    Włącznik czasowy 5 sek - po naciśnięciu pilota następuje załączenie przekaźnika na czas 5 sek
9
    Włącznik czasowy 10 sek - załączenie na czas 10 sek
10
    Włącznik czasowy 15 sek - załączenie na czas 15 sek
11
12
Programowanie
13
Niby opisane jest to na stronach dostawców - ale nie do końca - więc pełen opis programowania. Zalecane rozpoczęcie od punktu 8 - KASOWANIE
14
15
    Załączenie chwilowe (momentary) - naciskamy 1x przycisk programowania (potwierdzenie naciśnięcia krótkim błyskiem LED). LED po chwili włącza się na stałe na 8-10 sek. W tym czasie układ gotowy jest na przyjęcie nowego kodu. Wysłany kod zapamiętany jest w pamięci a potwierdzeniem tego jest podwójne "mrugnięcie" LEDa. LED gaśnie . Koniec procedury.
16
    Przełącznik (toggle) - naciskamy 2 x przycisk programowania. Dalej jak w pkt. 1
17
    Włącz/wyłącz (latched) - naciskamy 3 x przycisk programowania (potwierdzenie naciśnięcia krótkim błyskiem LED). LED po chwili włącza się na stałe na 8-10 sek. W tym czasie układ gotowy jest na przyjęcie nowego kodu. Wysłany kod zapamiętany jest w pamięci a potwierdzeniem tego jest podwójne "mrugnięcie" LEDa. LED pozostaje włączony Układ czeka na odbiór drugiego kodu. Po jego wysłaniu jest znowu podwójne "mrugnięcie" LEDa. LED gaśnie. Koniec procedury.
18
    Włącznik czasowy 5 sek - naciskamy 4 x przycisk programowania. Dalej jak w pkt. 1
19
    Włącznik czasowy 10 sek - naciskamy 5 x przycisk programowania. Dalej jak w pkt. 1
20
    Włącznik czasowy 15 sek - naciskamy 6 x przycisk programowania. Dalej jak w pkt. 1
21
    Włącznik czasowy 15 sek - naciskamy 7 x przycisk programowania. Dalej jak w pkt. 1
22
     KASOWANIE - usuwanie z pamięci wszystkich kodów. Nacisnąć 8 x przycisk. Każde naciśniecie sygnalizowane jest błyśnięciem. Po 8 naciśnięciu następują trzy mignięcia i pamięć kodów jest wyzerowana. Można też skasować pamięć naciskając przycisk raz przez ok 8 sek . Po puszczeniu przycisku LED zapali się na ok 3-4 sek i zgaśnie. Efekt działania ten sam.
23
24
Wszystkie te funkcje działają równolegle bo układ może zapamiętać do 50 kodów! Dodatkowo w trybie włącznika czasowego można skrócić czas załączenia poprzez wysłanie kodu WYŁĄCZ z wcześniej ustawionej funkcji latched.
25
 */
26
RADIO_BUTTON::RADIO_BUTTON(thread_data *my_data, const RADIO_EQ_CONFIG& cfg, RADIO_EQ_TYPE type)
27
195
{
28
195
    puts("RADIO_BUTTON::RADIO_BUTTON()");
29
195
    RADIO_EQ::m_my_data = my_data;
30
195
    RADIO_EQ::m_type = type;
31
195
    RADIO_EQ::m_config = cfg;
32
195
}
33
34
RADIO_BUTTON::~RADIO_BUTTON()
35
195
{
36
195
    puts("RADIO_BUTTON::~RADIO_BUTTON()");
37
195
}
38
39
STATE RADIO_BUTTON::getState()
40
23
{
41
23
    return m_state;
42
23
}
43
44
void RADIO_BUTTON::setState(STATE s)
45
6
{
46
6
    m_state = s;
47
6
}
48
49
std::string RADIO_BUTTON::getName()
50
12
{
51
12
    return RADIO_EQ::m_config.name;
52
12
}
53
54
std::string RADIO_BUTTON::getID()
55
38
{
56
38
    return RADIO_EQ::m_config.ID;
57
38
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/RADIO_433_eq/radio_433_eq.h
Line
Count
Source
1
#ifndef RADIO_SWITCH_H
2
#define RADIO_SWITCH_H
3
#include <gtest/gtest.h>
4
#include <gmock/gmock.h>
5
#include <map>
6
#include "../iDomStatus/idomstatus.h"
7
#include "../433MHz/RFLink/rflinkhandler.h"
8
9
#include "../433MHz/rc_433mhz.h"
10
#include "json.hpp"
11
12
struct WEATHER_STRUCT{
13
private:
14
    unsigned long int m_counter = 0;
15
protected:
16
    unsigned int m_humidity = 0;
17
    double m_temperature = 0.0;
18
    unsigned int m_barometricPressure = 0;
19
public:
20
    unsigned int getHumidity(){ return m_humidity; }
21
    double getTemperature(){ return m_temperature; }
22
    unsigned int getBarometricPressure(){ return m_barometricPressure; }
23
    std::string getDataString(){
24
        return "data: "+std::to_string(m_counter)+"\n"+"Humidity=" + std::to_string(getHumidity()) +"%\n"+
25
                "temperature= " + to_string_with_precision(getTemperature()) + "c\n"+
26
                "Pressure= " + std::to_string(getBarometricPressure())+ "kPa\n";
27
    }
28
29
    void putData(std::string data){
30
        std::string tempStr;
31
        int t = 0;
32
        ++m_counter;
33
        try{
34
            m_humidity = std::stoi( RFLinkHandler::getArgumentValueFromRFLinkMSG(data, "HUM") );
35
        }
36
        catch (...){ }
37
        try{
38
            m_barometricPressure = std::stoi( RFLinkHandler::getArgumentValueFromRFLinkMSG(data, "BARO") );
39
        }
40
        catch (...){ }
41
        try{
42
            tempStr = RFLinkHandler::getArgumentValueFromRFLinkMSG(data, "TEMP");
43
            std::stringstream ss;
44
            ss << std::hex << tempStr.substr(tempStr.size()-3,tempStr.size());
45
            ss >> t;
46
            m_temperature = t / 10.0;
47
            if(tempStr.at(0) == '8'){
48
                m_temperature *= -1.0;
49
            }
50
        }
51
        catch (...){ }
52
        //std::cout << "DUPA: "<<data<<" temp=" << m_temperature<< " hum="<<m_humidity<< std::endl;
53
    }
54
};
55
56
enum class RADIO_EQ_TYPE{
57
    SWITCH = 1,
58
    PIR,
59
    GATE,
60
    BUTTON,
61
    WEATHER_S,
62
    NONE
63
};
64
struct RADIO_EQ_CONFIG{
65
    std::string name = "NULL";
66
    std::string ID   = "NULL";
67
    std::string type = "NULL";
68
    std::string onCode  = "NULL";
69
    std::string offCode = "NULL";
70
    std::string on15sec = "NULL";
71
    std::string sunrise = "NULL";
72
    std::string sunset  = "NULL";
73
    std::string lock   = "NULL";
74
    std::string unlock = "NULL";
75
    void set(std::string type,
76
             std::string name,
77
             std::string ID,
78
             std::string onCode = "null",
79
             std::string offCode = "null",
80
             std::string on15sec = "null",
81
             std::string sunrise = "null",
82
             std::string sunset = "null",
83
             std::string lock = "null",
84
             std::string unlock = "null"){
85
        this->name = name;
86
        this->ID   = ID;
87
        this->type = type;
88
        this->onCode  = onCode;
89
        this->offCode = offCode;
90
        this->on15sec = on15sec;
91
        this->sunrise = sunrise;
92
        this->sunset  = sunset;
93
        this->lock   = lock;
94
        this->unlock = unlock;
95
    }
96
97
72
    nlohmann::json getJson(){
98
72
        nlohmann::json jj;
99
72
        jj["name"]  = name;
100
72
        jj["id"]    = ID;
101
72
        jj["type"]  = type;
102
72
        jj["ON"]    = onCode;
103
72
        jj["OFF"]   = offCode;
104
72
        jj["on15sec"] = on15sec;
105
72
        jj["sunrise"] = sunrise;
106
72
        jj["sunset"]  = sunset;
107
72
        jj["lock"]   = lock;
108
72
        jj["unlock"] = unlock;
109
72
        return jj;
110
72
    }
111
};
112
113
class RADIO_EQ{
114
public:
115
    RADIO_EQ();
116
    virtual ~RADIO_EQ();
117
    virtual STATE getState() = 0;
118
    virtual std::string getName() = 0;
119
    virtual std::string getID() = 0;
120
    virtual RADIO_EQ_TYPE getType();
121
protected:
122
    thread_data *m_my_data;
123
    RADIO_EQ_TYPE m_type;
124
public:
125
    RADIO_EQ_CONFIG m_config;
126
};
127
class RADIO_WEATHER_STATION: public RADIO_EQ
128
{
129
    STATE m_state = STATE::UNDEFINE;
130
131
public:
132
    RADIO_WEATHER_STATION(thread_data * my_data, const RADIO_EQ_CONFIG& cfg, RADIO_EQ_TYPE type);
133
    ~RADIO_WEATHER_STATION();
134
    STATE getState();
135
    std::string getName();
136
    std::string getID();
137
    // data
138
    WEATHER_STRUCT data;
139
};
140
class RADIO_BUTTON: public RADIO_EQ
141
{
142
    STATE m_state = STATE::UNDEFINE;
143
144
public:
145
    RADIO_BUTTON(thread_data * my_data, const RADIO_EQ_CONFIG& cfg, RADIO_EQ_TYPE type);
146
    ~RADIO_BUTTON();
147
    STATE getState();
148
    void setState(STATE s);
149
    std::string getName();
150
    std::string getID();
151
};
152
153
class RADIO_SWITCH: public RADIO_EQ
154
{
155
#ifdef BT_TEST
156
public:
157
#endif
158
    RC_433MHz main433MHz;
159
    STATE m_state = STATE::UNDEFINE;
160
public:
161
    RADIO_SWITCH(thread_data * my_data, const RADIO_EQ_CONFIG& cfg, RADIO_EQ_TYPE type);
162
    ~RADIO_SWITCH();
163
    void on();
164
    void off();
165
    void onFor15sec();
166
    void onSunrise();
167
    void onSunset();
168
    void onLockHome();
169
    void onUnlockHome();
170
    STATE getState();
171
    std::string getName();
172
    std::string getID();
173
    void setCode(RADIO_EQ_CONFIG cfg);
174
    STATE m_sunrise = STATE::UNDEFINE;
175
    STATE m_sunset  = STATE::UNDEFINE;
176
};
177
178
class RADIO_EQ_CONTAINER
179
{
180
    std::map <std::string, RADIO_EQ* > m_radioEqMap;
181
    thread_data * my_data;
182
    nlohmann::json m_configJson;
183
public:
184
    RADIO_EQ_CONTAINER(thread_data * my_data);
185
    virtual ~RADIO_EQ_CONTAINER();
186
    void addRadioEq(RADIO_EQ_CONFIG cfg, RADIO_EQ_TYPE type);
187
    void addRadioEq(RADIO_EQ_CONFIG cfg, const std::string& type);
188
    void deleteRadioEq(const std::string &name);
189
    virtual RADIO_EQ* getEqPointer(std::string name);
190
    std::vector<RADIO_SWITCH*> getSwitchPointerVector();
191
    std::vector<RADIO_BUTTON*> getButtonPointerVector();
192
    std::vector<RADIO_WEATHER_STATION *> getWeather_StationPtrVector();
193
    std::string listAllName();
194
    bool nameExist(const std::string &name);
195
    void loadConfig(const std::string &filePath);
196
    void saveConfig(const std::string &filePath);
197
};
198
199
class RADIO_EQ_CONTAINER_STUB : public RADIO_EQ_CONTAINER
200
{
201
    thread_data * k;
202
public:
203
    RADIO_EQ_CONTAINER_STUB(thread_data * k):RADIO_EQ_CONTAINER(k){this->k = k;}
204
205
    virtual ~RADIO_EQ_CONTAINER_STUB(){puts("~RADIO_EQ_CONTAINER_STUB()");}
206
    MOCK_METHOD1(getEqPointer, RADIO_EQ*(std::string name));
207
};
208
209
#endif // RADIO_SWITCH_H
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/RADIO_433_eq/test/radio_433_test.cpp
Line
Count
Source
1
#include <gtest/gtest.h>
2
#include <gmock/gmock.h>
3
#include "../radio_433_eq.h"
4
#include "../../iDomTools/test/iDomTools_fixture.h"
5
6
RC_433MHz::RC_433MHz(thread_data *test_my_data)
7
973
{
8
973
    this->m_my_data = test_my_data;
9
973
}
10
void RC_433MHz::sendCode(const std::string& code)
11
28
{
12
28
    std::cout << "sendCode(): " << code << std::endl;
13
28
}
14
15
class Switch_Class_fixture : public iDomTOOLS_ClassTest
16
{
17
18
};
19
TEST_F(Switch_Class_fixture, getSwitchPointerVector)
20
1
{
21
1
    auto v = test_rec->getSwitchPointerVector();
22
1
    EXPECT_EQ(v.size(),5);
23
1
}
24
25
TEST_F(Switch_Class_fixture, getButtonPointerVector)
26
1
{
27
1
    auto v = test_rec->getButtonPointerVector();
28
1
    EXPECT_EQ(v.size(),1);
29
1
}
30
31
TEST_F(Switch_Class_fixture, switch_alarm_on)
32
1
{
33
1
    RADIO_SWITCH* ptr = dynamic_cast<RADIO_SWITCH*>(test_rec->getEqPointer("ALARM"));
34
1
35
1
    EXPECT_EQ(ptr->getType(),RADIO_EQ_TYPE::SWITCH);
36
1
    puts("radio switch type");
37
1
    EXPECT_EQ(ptr->getState(),STATE::UNDEFINE);
38
1
    puts("radio switch state");
39
1
    ptr->on();
40
1
    EXPECT_EQ(ptr->getState(),STATE::ON);
41
1
    ptr->off();
42
1
    EXPECT_EQ(ptr->getState(),STATE::OFF);
43
1
    ptr->onSunset();
44
1
    EXPECT_EQ(ptr->getState(),STATE::OFF);
45
1
}
46
47
TEST_F(Switch_Class_fixture, weatherStruct)
48
1
{
49
1
    WEATHER_STRUCT test_WS;
50
2
    EXPECT_DOUBLE_EQ(0.0, test_WS.getTemperature()) << "Tempertura zla";
51
1
52
1
    test_WS.putData("20;03;LaCrosse;ID=0506;TEMP=0137;");
53
2
    EXPECT_DOUBLE_EQ(31.1, test_WS.getTemperature()) << "Tempertura zla";
54
1
55
1
    test_WS.putData("20;03;LaCrosse;ID=0506;TEMP=8130;BARO=999;");
56
2
    EXPECT_DOUBLE_EQ(-30.4, test_WS.getTemperature()) << "Tempertura zla";
57
1
58
2
    EXPECT_EQ(999, test_WS.getBarometricPressure()) << "zle cisneinie";
59
1
60
1
    std::string retString = test_WS.getDataString();
61
1
    EXPECT_THAT(retString, testing::HasSubstr("Pressure= 999kPa"));
62
1
}
63
64
TEST_F(Switch_Class_fixture, read_write_config_json)
65
1
{
66
1
    auto v = test_rec->getSwitchPointerVector();
67
1
    EXPECT_EQ(v.size(),5);
68
1
    test_rec->saveConfig(test_server_set.radio433MHzConfigFile);
69
1
    v = test_rec->getSwitchPointerVector();
70
1
    EXPECT_EQ(v.size(),5);
71
1
}
72
TEST_F(Switch_Class_fixture, addUnexistsRadioEq)
73
1
{
74
1
    RADIO_EQ_CONFIG tCfg;
75
1
    tCfg.name = "cyniu";
76
1
    tCfg.ID = "8899";
77
1
    std::string _name = tCfg.name;
78
1
    EXPECT_FALSE(test_rec->nameExist(_name));
79
1
    test_rec->addRadioEq(tCfg, "PIR");
80
1
    EXPECT_FALSE(test_rec->nameExist(_name));
81
1
}
82
83
TEST_F(Switch_Class_fixture, add_and_erase_switch)
84
1
{
85
1
    RADIO_EQ_CONFIG tCfg;
86
1
    tCfg.name = "test";
87
1
    test_rec->addRadioEq(tCfg, RADIO_EQ_TYPE::SWITCH);
88
1
    auto v = test_rec->getSwitchPointerVector();
89
1
    EXPECT_EQ(v.size(),6);
90
1
    test_rec->saveConfig(test_server_set.radio433MHzConfigFile);
91
1
    v = test_rec->getSwitchPointerVector();
92
1
    EXPECT_EQ(v.size(),6);
93
1
94
1
    ///////delete
95
1
    test_rec->deleteRadioEq(tCfg.name);
96
1
    v = test_rec->getSwitchPointerVector();
97
1
    EXPECT_EQ(v.size(),5);
98
1
    test_rec->saveConfig(test_server_set.radio433MHzConfigFile);
99
1
    v = test_rec->getSwitchPointerVector();
100
1
    EXPECT_EQ(v.size(),5);
101
1
}
102
103
TEST_F(Switch_Class_fixture, loadConfig)
104
1
{
105
1
    RADIO_EQ_CONTAINER test_rec(&test_my_data);
106
1
    test_rec.loadConfig("/mnt/ramdisk/433_eq_conf_fake.json");
107
1
108
1
    EXPECT_FALSE(test_my_data.main_REC->nameExist("firstt"));
109
1
    EXPECT_TRUE(test_my_data.main_REC->nameExist("locker"));
110
1
111
1
    //test_rec.loadConfig("/mnt/ramdisk/433_eq_conf_fake.json");
112
1
}
113
114
TEST_F(Switch_Class_fixture, getUnexistPtr)
115
1
{
116
1
    EXPECT_THROW(test_my_data.main_REC->getEqPointer("kokos"),std::string);
117
1
}
118
119
TEST_F(Switch_Class_fixture, onLock_onUnlock_HOME)
120
1
{
121
1
    RADIO_EQ_CONFIG tCfg;
122
1
    tCfg.name = "cyniu";
123
1
    tCfg.ID = "8899";
124
1
    tCfg.lock =  "ON";
125
1
126
1
    auto testRadioS = static_cast<RADIO_SWITCH*>(test_rec->getEqPointer("C"));
127
1
    testRadioS->setCode(tCfg);
128
1
    testRadioS->onLockHome();
129
1
    std::string eventStr = test_my_data.myEventHandler.run("iDom")->getEvent();
130
1
    EXPECT_THAT(eventStr, testing::HasSubstr("cyniu ON due to 433MHz button pressed"));
131
1
132
1
    tCfg.lock =  "OFF";
133
1
    testRadioS->setCode(tCfg);
134
1
    testRadioS->onLockHome();
135
1
    eventStr = test_my_data.myEventHandler.run("iDom")->getEvent();
136
1
    EXPECT_THAT(eventStr, testing::HasSubstr("cyniu OFF due to 433MHz button pressed"));
137
1
138
1
    ////////////////////// unlock
139
1
    tCfg.unlock =  "ON";
140
1
141
1
    testRadioS->setCode(tCfg);
142
1
    testRadioS->onUnlockHome();
143
1
     eventStr = test_my_data.myEventHandler.run("iDom")->getEvent();
144
1
    EXPECT_THAT(eventStr, testing::HasSubstr("cyniu ON due to 433MHz button pressed"));
145
1
146
1
    tCfg.unlock =  "OFF";
147
1
    testRadioS->setCode(tCfg);
148
1
    testRadioS->onUnlockHome();
149
1
    eventStr = test_my_data.myEventHandler.run("iDom")->getEvent();
150
1
    EXPECT_THAT(eventStr, testing::HasSubstr("cyniu OFF due to 433MHz button pressed"));
151
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/RADIO_433_eq/radio_button.cpp
Line
Count
Source
1
#include "radio_433_eq.h"
2
/*
3
 * Najpierw możliwe do uzyskania funkcje załączania
4
5
    Załączenie chwilowe (momentary) - przekaźnik jest załączony tak długo jak długo naciskany jest klawisz pilota - nadawany kod
6
    Przełącznik (toggle) - przekaźnik jest załączany /wyłączany przy kolejnych naciśnięciach tego samego klawisza - nadajemy ten sam kod
7
    Włącz/wyłącz (latched) - przekaźnik jest załączany jednym kodem a wyłączany innym
8
    Włącznik czasowy 5 sek - po naciśnięciu pilota następuje załączenie przekaźnika na czas 5 sek
9
    Włącznik czasowy 10 sek - załączenie na czas 10 sek
10
    Włącznik czasowy 15 sek - załączenie na czas 15 sek
11
12
Programowanie
13
Niby opisane jest to na stronach dostawców - ale nie do końca - więc pełen opis programowania. Zalecane rozpoczęcie od punktu 8 - KASOWANIE
14
15
    Załączenie chwilowe (momentary) - naciskamy 1x przycisk programowania (potwierdzenie naciśnięcia krótkim błyskiem LED). LED po chwili włącza się na stałe na 8-10 sek. W tym czasie układ gotowy jest na przyjęcie nowego kodu. Wysłany kod zapamiętany jest w pamięci a potwierdzeniem tego jest podwójne "mrugnięcie" LEDa. LED gaśnie . Koniec procedury.
16
    Przełącznik (toggle) - naciskamy 2 x przycisk programowania. Dalej jak w pkt. 1
17
    Włącz/wyłącz (latched) - naciskamy 3 x przycisk programowania (potwierdzenie naciśnięcia krótkim błyskiem LED). LED po chwili włącza się na stałe na 8-10 sek. W tym czasie układ gotowy jest na przyjęcie nowego kodu. Wysłany kod zapamiętany jest w pamięci a potwierdzeniem tego jest podwójne "mrugnięcie" LEDa. LED pozostaje włączony Układ czeka na odbiór drugiego kodu. Po jego wysłaniu jest znowu podwójne "mrugnięcie" LEDa. LED gaśnie. Koniec procedury.
18
    Włącznik czasowy 5 sek - naciskamy 4 x przycisk programowania. Dalej jak w pkt. 1
19
    Włącznik czasowy 10 sek - naciskamy 5 x przycisk programowania. Dalej jak w pkt. 1
20
    Włącznik czasowy 15 sek - naciskamy 6 x przycisk programowania. Dalej jak w pkt. 1
21
    Włącznik czasowy 15 sek - naciskamy 7 x przycisk programowania. Dalej jak w pkt. 1
22
     KASOWANIE - usuwanie z pamięci wszystkich kodów. Nacisnąć 8 x przycisk. Każde naciśniecie sygnalizowane jest błyśnięciem. Po 8 naciśnięciu następują trzy mignięcia i pamięć kodów jest wyzerowana. Można też skasować pamięć naciskając przycisk raz przez ok 8 sek . Po puszczeniu przycisku LED zapali się na ok 3-4 sek i zgaśnie. Efekt działania ten sam.
23
24
Wszystkie te funkcje działają równolegle bo układ może zapamiętać do 50 kodów! Dodatkowo w trybie włącznika czasowego można skrócić czas załączenia poprzez wysłanie kodu WYŁĄCZ z wcześniej ustawionej funkcji latched.
25
 */
26
RADIO_BUTTON::RADIO_BUTTON(thread_data *my_data, const RADIO_EQ_CONFIG& cfg, RADIO_EQ_TYPE type)
27
195
{
28
195
    puts("RADIO_BUTTON::RADIO_BUTTON()");
29
195
    RADIO_EQ::m_my_data = my_data;
30
195
    RADIO_EQ::m_type = type;
31
195
    RADIO_EQ::m_config = cfg;
32
195
}
33
34
RADIO_BUTTON::~RADIO_BUTTON()
35
195
{
36
195
    puts("RADIO_BUTTON::~RADIO_BUTTON()");
37
195
}
38
39
STATE RADIO_BUTTON::getState()
40
23
{
41
23
    return m_state;
42
23
}
43
44
void RADIO_BUTTON::setState(STATE s)
45
6
{
46
6
    m_state = s;
47
6
}
48
49
std::string RADIO_BUTTON::getName()
50
12
{
51
12
    return RADIO_EQ::m_config.name;
52
12
}
53
54
std::string RADIO_BUTTON::getID()
55
38
{
56
38
    return RADIO_EQ::m_config.ID;
57
38
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/THERMOMETER_CONTAINER/test/thermometer_container_BT.cpp
Line
Count
Source
1
#include <gtest/gtest.h>
2
#include <gmock/gmock.h>
3
#include "../../iDomTools/test/iDomTools_fixture.h"
4
#include "../thermometer_container.h"
5
6
class Thermometer_container_fixture :  public ::testing::Test //public iDomTOOLS_ClassTest
7
{
8
public:
9
    THERMOMETER_CONTAINER testThermo;
10
    std::string termoName = "test_thermometer";
11
    std::vector<std::string> v;
12
13
    void SetUp() final
14
4
    {
15
4
        std::vector<std::string> v = {"10.2","11.22"};
16
4
        testThermo.add("inside");
17
4
        testThermo.add("outside");
18
4
        testThermo.updateAll(&v);
19
4
        v = {"20.2","21.22"};
20
4
        testThermo.updateAll(&v);
21
4
        std::cout << "temepratura inside" << testThermo.getTemp("inside") << std::endl;
22
4
        std::cout << "temepratura outside" << testThermo.getTemp("outside") << std::endl;
23
4
        testThermo.updateStats("inside");
24
4
        testThermo.updateStats("outside");
25
4
        std::cout << "rozmiar mapy termoetrow: " << testThermo.sizeOf() << std::endl;
26
4
        testThermo.showAll();
27
4
        puts("SetUp() Thermometer_container_fixture");
28
4
        puts("--------------------------------------");
29
4
    }
30
};
31
TEST_F(Thermometer_container_fixture, returnUnexistPTR)
32
1
{
33
1
    EXPECT_THROW(testThermo.returnThermometerPtr("fake"),std::string);
34
1
}
35
36
TEST_F(Thermometer_container_fixture, getStatsByName)
37
1
{
38
1
    std::string returnedStr = testThermo.getStatsByName("inside");
39
1
    std::cout << "zwrocono " << returnedStr << std::endl;
40
1
    EXPECT_THAT(returnedStr, testing::HasSubstr("min: 20.2"));
41
1
    EXPECT_THAT(returnedStr, testing::HasSubstr("max: 20.2"));
42
1
}
43
44
TEST_F(Thermometer_container_fixture, getLast2)
45
1
{
46
1
    std::cout << "rozmiar mapy termoetrow: " << testThermo.sizeOf() << std::endl;
47
1
    testThermo.updateStats("inside");
48
1
    testThermo.updateStats("outside");
49
1
    testThermo.showAll();
50
1
    v = {"44.4","45.45"};
51
1
    testThermo.updateAll(&v);
52
1
    testThermo.updateStats("inside");
53
1
    testThermo.updateStats("outside");
54
1
    std::string returnedStr = testThermo.getStatsByName("inside");
55
1
    std::cout << "zwrocono " << returnedStr <<"||"<< std::endl;
56
1
    auto v = testThermo.getLast2("inside");
57
1
    EXPECT_EQ(v.first, 20.2);
58
1
    EXPECT_EQ(v.second, 44.4);
59
1
}
60
61
TEST_F(Thermometer_container_fixture, isMoreDiff)
62
1
{
63
1
    std::cout << "rozmiar mapy termoetrow: " << testThermo.sizeOf() << std::endl;
64
1
    testThermo.updateStats("inside");
65
1
    testThermo.updateStats("outside");
66
1
    testThermo.showAll();
67
1
    v = {"24.4","45.45"};
68
1
    testThermo.updateAll(&v);
69
1
    testThermo.updateStats("inside");
70
1
    testThermo.updateStats("outside");
71
1
    EXPECT_FALSE(testThermo.isMoreDiff("inside",15.5));
72
1
    EXPECT_TRUE(testThermo.isMoreDiff("outside",15.5));
73
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/RADIO_433_eq/radio_433_eq.h
Line
Count
Source
1
#ifndef RADIO_SWITCH_H
2
#define RADIO_SWITCH_H
3
#include <gtest/gtest.h>
4
#include <gmock/gmock.h>
5
#include <map>
6
#include "../iDomStatus/idomstatus.h"
7
#include "../433MHz/RFLink/rflinkhandler.h"
8
9
#include "../433MHz/rc_433mhz.h"
10
#include "json.hpp"
11
12
struct WEATHER_STRUCT{
13
private:
14
    unsigned long int m_counter = 0;
15
protected:
16
    unsigned int m_humidity = 0;
17
    double m_temperature = 0.0;
18
    unsigned int m_barometricPressure = 0;
19
public:
20
4
    unsigned int getHumidity(){ return m_humidity; }
21
7
    double getTemperature(){ return m_temperature; }
22
3
    unsigned int getBarometricPressure(){ return m_barometricPressure; }
23
2
    std::string getDataString(){
24
2
        return "data: "+std::to_string(m_counter)+"\n"+"Humidity=" + std::to_string(getHumidity()) +"%\n"+
25
2
                "temperature= " + to_string_with_precision(getTemperature()) + "c\n"+
26
2
                "Pressure= " + std::to_string(getBarometricPressure())+ "kPa\n";
27
2
    }
28
29
5
    void putData(std::string data){
30
5
        std::string tempStr;
31
5
        int t = 0;
32
5
        ++m_counter;
33
5
        try{
34
5
            m_humidity = std::stoi( RFLinkHandler::getArgumentValueFromRFLinkMSG(data, "HUM") );
35
5
        }
36
5
        catch (...){ }
37
5
        try{
38
5
            m_barometricPressure = std::stoi( RFLinkHandler::getArgumentValueFromRFLinkMSG(data, "BARO") );
39
5
        }
40
5
        catch (...){ }
41
5
        try{
42
5
            tempStr = RFLinkHandler::getArgumentValueFromRFLinkMSG(data, "TEMP");
43
5
            std::stringstream ss;
44
5
            ss << std::hex << tempStr.substr(tempStr.size()-3,tempStr.size());
45
5
            ss >> t;
46
5
            m_temperature = t / 10.0;
47
5
            if(tempStr.at(0) == '8'){
48
2
                m_temperature *= -1.0;
49
2
            }
50
5
        }
51
5
        catch (...){ }
52
5
        //std::cout << "DUPA: "<<data<<" temp=" << m_temperature<< " hum="<<m_humidity<< std::endl;
53
5
    }
54
};
55
56
enum class RADIO_EQ_TYPE{
57
    SWITCH = 1,
58
    PIR,
59
    GATE,
60
    BUTTON,
61
    WEATHER_S,
62
    NONE
63
};
64
struct RADIO_EQ_CONFIG{
65
    std::string name = "NULL";
66
    std::string ID   = "NULL";
67
    std::string type = "NULL";
68
    std::string onCode  = "NULL";
69
    std::string offCode = "NULL";
70
    std::string on15sec = "NULL";
71
    std::string sunrise = "NULL";
72
    std::string sunset  = "NULL";
73
    std::string lock   = "NULL";
74
    std::string unlock = "NULL";
75
    void set(std::string type,
76
             std::string name,
77
             std::string ID,
78
             std::string onCode = "null",
79
             std::string offCode = "null",
80
             std::string on15sec = "null",
81
             std::string sunrise = "null",
82
             std::string sunset = "null",
83
             std::string lock = "null",
84
             std::string unlock = "null"){
85
        this->name = name;
86
        this->ID   = ID;
87
        this->type = type;
88
        this->onCode  = onCode;
89
        this->offCode = offCode;
90
        this->on15sec = on15sec;
91
        this->sunrise = sunrise;
92
        this->sunset  = sunset;
93
        this->lock   = lock;
94
        this->unlock = unlock;
95
    }
96
97
    nlohmann::json getJson(){
98
        nlohmann::json jj;
99
        jj["name"]  = name;
100
        jj["id"]    = ID;
101
        jj["type"]  = type;
102
        jj["ON"]    = onCode;
103
        jj["OFF"]   = offCode;
104
        jj["on15sec"] = on15sec;
105
        jj["sunrise"] = sunrise;
106
        jj["sunset"]  = sunset;
107
        jj["lock"]   = lock;
108
        jj["unlock"] = unlock;
109
        return jj;
110
    }
111
};
112
113
class RADIO_EQ{
114
public:
115
    RADIO_EQ();
116
    virtual ~RADIO_EQ();
117
    virtual STATE getState() = 0;
118
    virtual std::string getName() = 0;
119
    virtual std::string getID() = 0;
120
    virtual RADIO_EQ_TYPE getType();
121
protected:
122
    thread_data *m_my_data;
123
    RADIO_EQ_TYPE m_type;
124
public:
125
    RADIO_EQ_CONFIG m_config;
126
};
127
class RADIO_WEATHER_STATION: public RADIO_EQ
128
{
129
    STATE m_state = STATE::UNDEFINE;
130
131
public:
132
    RADIO_WEATHER_STATION(thread_data * my_data, const RADIO_EQ_CONFIG& cfg, RADIO_EQ_TYPE type);
133
    ~RADIO_WEATHER_STATION();
134
    STATE getState();
135
    std::string getName();
136
    std::string getID();
137
    // data
138
    WEATHER_STRUCT data;
139
};
140
class RADIO_BUTTON: public RADIO_EQ
141
{
142
    STATE m_state = STATE::UNDEFINE;
143
144
public:
145
    RADIO_BUTTON(thread_data * my_data, const RADIO_EQ_CONFIG& cfg, RADIO_EQ_TYPE type);
146
    ~RADIO_BUTTON();
147
    STATE getState();
148
    void setState(STATE s);
149
    std::string getName();
150
    std::string getID();
151
};
152
153
class RADIO_SWITCH: public RADIO_EQ
154
{
155
#ifdef BT_TEST
156
public:
157
#endif
158
    RC_433MHz main433MHz;
159
    STATE m_state = STATE::UNDEFINE;
160
public:
161
    RADIO_SWITCH(thread_data * my_data, const RADIO_EQ_CONFIG& cfg, RADIO_EQ_TYPE type);
162
    ~RADIO_SWITCH();
163
    void on();
164
    void off();
165
    void onFor15sec();
166
    void onSunrise();
167
    void onSunset();
168
    void onLockHome();
169
    void onUnlockHome();
170
    STATE getState();
171
    std::string getName();
172
    std::string getID();
173
    void setCode(RADIO_EQ_CONFIG cfg);
174
    STATE m_sunrise = STATE::UNDEFINE;
175
    STATE m_sunset  = STATE::UNDEFINE;
176
};
177
178
class RADIO_EQ_CONTAINER
179
{
180
    std::map <std::string, RADIO_EQ* > m_radioEqMap;
181
    thread_data * my_data;
182
    nlohmann::json m_configJson;
183
public:
184
    RADIO_EQ_CONTAINER(thread_data * my_data);
185
    virtual ~RADIO_EQ_CONTAINER();
186
    void addRadioEq(RADIO_EQ_CONFIG cfg, RADIO_EQ_TYPE type);
187
    void addRadioEq(RADIO_EQ_CONFIG cfg, const std::string& type);
188
    void deleteRadioEq(const std::string &name);
189
    virtual RADIO_EQ* getEqPointer(std::string name);
190
    std::vector<RADIO_SWITCH*> getSwitchPointerVector();
191
    std::vector<RADIO_BUTTON*> getButtonPointerVector();
192
    std::vector<RADIO_WEATHER_STATION *> getWeather_StationPtrVector();
193
    std::string listAllName();
194
    bool nameExist(const std::string &name);
195
    void loadConfig(const std::string &filePath);
196
    void saveConfig(const std::string &filePath);
197
};
198
199
class RADIO_EQ_CONTAINER_STUB : public RADIO_EQ_CONTAINER
200
{
201
    thread_data * k;
202
public:
203
    RADIO_EQ_CONTAINER_STUB(thread_data * k):RADIO_EQ_CONTAINER(k){this->k = k;}
204
205
    virtual ~RADIO_EQ_CONTAINER_STUB(){puts("~RADIO_EQ_CONTAINER_STUB()");}
206
    MOCK_METHOD1(getEqPointer, RADIO_EQ*(std::string name));
207
};
208
209
#endif // RADIO_SWITCH_H
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/THERMOMETER_CONTAINER/thermometer_container.cpp
Line
Count
Source (jump to first uncovered line)
1
#include "thermometer_container.h"
2
3
THERMOMETER *THERMOMETER_CONTAINER::returnThermometerPtr(const std::string& name)
4
308
{
5
308
    auto m = thermoMap.find(name);
6
308
    if (m != thermoMap.end())
7
306
        return &(m->second);
8
2
    else
9
2
    {
10
2
      throw std::string("thermometer not found!");
11
2
    }
12
0
}
13
14
THERMOMETER_CONTAINER::THERMOMETER_CONTAINER()
15
388
{
16
388
}
17
18
THERMOMETER::THERMOMETER(int iter):m_stats(iter)
19
776
{
20
776
}
21
22
void THERMOMETER_CONTAINER::add(const std::string &name)
23
776
{
24
776
    auto pair = std::make_pair(name, THERMOMETER(15));
25
776
    thermoMap.insert(pair);
26
776
}
27
28
void THERMOMETER_CONTAINER::setTemp(const std::string &name, double value)
29
48
{
30
48
    returnThermometerPtr(name)->m_thermometer.oldTemp = returnThermometerPtr(name)->m_thermometer.newTemp;
31
48
    returnThermometerPtr(name)->m_thermometer.newTemp = value;
32
48
}
33
34
double THERMOMETER_CONTAINER::getTemp(const std::string &name)
35
24
{
36
24
    return returnThermometerPtr(name)->m_thermometer.newTemp;
37
24
}
38
39
double THERMOMETER_CONTAINER::getOldTemp(const std::string &name)
40
16
{
41
16
    return returnThermometerPtr(name)->m_thermometer.oldTemp;
42
16
}
43
44
TEMPERATURE_STATE THERMOMETER_CONTAINER::getLastState(const std::string &name)
45
28
{
46
28
    return returnThermometerPtr(name)->m_thermometer.lastState;
47
28
}
48
49
void THERMOMETER_CONTAINER::setState(const std::string &name, TEMPERATURE_STATE state)
50
16
{
51
16
    returnThermometerPtr(name)->m_thermometer.lastState = state;
52
16
}
53
54
void THERMOMETER_CONTAINER::updateAll(std::vector<std::string> *vectorThermo)
55
24
{
56
24
    std::string in  = vectorThermo->at(0);
57
24
    std::string out = vectorThermo->at(1);
58
24
    setTemp("inside", std::stod(in));
59
24
    setTemp("outside",std::stod(out));
60
24
}
61
62
void THERMOMETER_CONTAINER::updateStats(const std::string &name)
63
28
{
64
28
    returnThermometerPtr(name)->m_stats.push_back(returnThermometerPtr(name)->m_thermometer.newTemp);
65
28
}
66
67
std::string THERMOMETER_CONTAINER::getStatsByName(const std::string &name)
68
4
{
69
4
    return returnThermometerPtr(name)->m_stats.stats();
70
4
}
71
72
bool THERMOMETER_CONTAINER::isMoreDiff(const std::string &name, double diff)
73
14
{
74
14
    return returnThermometerPtr(name)->m_stats.isMoreDiff(diff);
75
14
}
76
77
std::pair<double, double> THERMOMETER_CONTAINER::getLast2(const std::string &name)
78
5
{
79
5
    return returnThermometerPtr(name)->m_stats.getLast2();
80
5
}
81
82
int THERMOMETER_CONTAINER::sizeOf()
83
6
{
84
6
    return static_cast<int>(thermoMap.size());
85
6
}
86
87
void THERMOMETER_CONTAINER::showAll()
88
6
{
89
6
    for(auto n : thermoMap)
90
12
    {
91
12
        std::cout << n.first << " ";
92
12
    }
93
6
    std::cout << std::endl << "koniec prointowania w " << std::endl;
94
6
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/RADIO_433_eq/test/radio_433_test.cpp
Line
Count
Source
1
#include <gtest/gtest.h>
2
#include <gmock/gmock.h>
3
#include "../radio_433_eq.h"
4
#include "../../iDomTools/test/iDomTools_fixture.h"
5
6
RC_433MHz::RC_433MHz(thread_data *test_my_data)
7
973
{
8
973
    this->m_my_data = test_my_data;
9
973
}
10
void RC_433MHz::sendCode(const std::string& code)
11
28
{
12
28
    std::cout << "sendCode(): " << code << std::endl;
13
28
}
14
15
class Switch_Class_fixture : public iDomTOOLS_ClassTest
16
{
17
18
};
19
TEST_F(Switch_Class_fixture, getSwitchPointerVector)
20
1
{
21
1
    auto v = test_rec->getSwitchPointerVector();
22
1
    EXPECT_EQ(v.size(),5);
23
1
}
24
25
TEST_F(Switch_Class_fixture, getButtonPointerVector)
26
1
{
27
1
    auto v = test_rec->getButtonPointerVector();
28
1
    EXPECT_EQ(v.size(),1);
29
1
}
30
31
TEST_F(Switch_Class_fixture, switch_alarm_on)
32
1
{
33
1
    RADIO_SWITCH* ptr = dynamic_cast<RADIO_SWITCH*>(test_rec->getEqPointer("ALARM"));
34
1
35
1
    EXPECT_EQ(ptr->getType(),RADIO_EQ_TYPE::SWITCH);
36
1
    puts("radio switch type");
37
1
    EXPECT_EQ(ptr->getState(),STATE::UNDEFINE);
38
1
    puts("radio switch state");
39
1
    ptr->on();
40
1
    EXPECT_EQ(ptr->getState(),STATE::ON);
41
1
    ptr->off();
42
1
    EXPECT_EQ(ptr->getState(),STATE::OFF);
43
1
    ptr->onSunset();
44
1
    EXPECT_EQ(ptr->getState(),STATE::OFF);
45
1
}
46
47
TEST_F(Switch_Class_fixture, weatherStruct)
48
1
{
49
1
    WEATHER_STRUCT test_WS;
50
3
    EXPECT_DOUBLE_EQ(0.0, test_WS.getTemperature()) << "Tempertura zla";
51
1
52
1
    test_WS.putData("20;03;LaCrosse;ID=0506;TEMP=0137;");
53
3
    EXPECT_DOUBLE_EQ(31.1, test_WS.getTemperature()) << "Tempertura zla";
54
1
55
1
    test_WS.putData("20;03;LaCrosse;ID=0506;TEMP=8130;BARO=999;");
56
3
    EXPECT_DOUBLE_EQ(-30.4, test_WS.getTemperature()) << "Tempertura zla";
57
1
58
3
    EXPECT_EQ(999, test_WS.getBarometricPressure()) << "zle cisneinie";
59
1
60
1
    std::string retString = test_WS.getDataString();
61
1
    EXPECT_THAT(retString, testing::HasSubstr("Pressure= 999kPa"));
62
1
}
63
64
TEST_F(Switch_Class_fixture, read_write_config_json)
65
1
{
66
1
    auto v = test_rec->getSwitchPointerVector();
67
1
    EXPECT_EQ(v.size(),5);
68
1
    test_rec->saveConfig(test_server_set.radio433MHzConfigFile);
69
1
    v = test_rec->getSwitchPointerVector();
70
1
    EXPECT_EQ(v.size(),5);
71
1
}
72
TEST_F(Switch_Class_fixture, addUnexistsRadioEq)
73
1
{
74
1
    RADIO_EQ_CONFIG tCfg;
75
1
    tCfg.name = "cyniu";
76
1
    tCfg.ID = "8899";
77
1
    std::string _name = tCfg.name;
78
1
    EXPECT_FALSE(test_rec->nameExist(_name));
79
1
    test_rec->addRadioEq(tCfg, "PIR");
80
1
    EXPECT_FALSE(test_rec->nameExist(_name));
81
1
}
82
83
TEST_F(Switch_Class_fixture, add_and_erase_switch)
84
1
{
85
1
    RADIO_EQ_CONFIG tCfg;
86
1
    tCfg.name = "test";
87
1
    test_rec->addRadioEq(tCfg, RADIO_EQ_TYPE::SWITCH);
88
1
    auto v = test_rec->getSwitchPointerVector();
89
1
    EXPECT_EQ(v.size(),6);
90
1
    test_rec->saveConfig(test_server_set.radio433MHzConfigFile);
91
1
    v = test_rec->getSwitchPointerVector();
92
1
    EXPECT_EQ(v.size(),6);
93
1
94
1
    ///////delete
95
1
    test_rec->deleteRadioEq(tCfg.name);
96
1
    v = test_rec->getSwitchPointerVector();
97
1
    EXPECT_EQ(v.size(),5);
98
1
    test_rec->saveConfig(test_server_set.radio433MHzConfigFile);
99
1
    v = test_rec->getSwitchPointerVector();
100
1
    EXPECT_EQ(v.size(),5);
101
1
}
102
103
TEST_F(Switch_Class_fixture, loadConfig)
104
1
{
105
1
    RADIO_EQ_CONTAINER test_rec(&test_my_data);
106
1
    test_rec.loadConfig("/mnt/ramdisk/433_eq_conf_fake.json");
107
1
108
1
    EXPECT_FALSE(test_my_data.main_REC->nameExist("firstt"));
109
1
    EXPECT_TRUE(test_my_data.main_REC->nameExist("locker"));
110
1
111
1
    //test_rec.loadConfig("/mnt/ramdisk/433_eq_conf_fake.json");
112
1
}
113
114
TEST_F(Switch_Class_fixture, getUnexistPtr)
115
1
{
116
1
    EXPECT_THROW(test_my_data.main_REC->getEqPointer("kokos"),std::string);
117
1
}
118
119
TEST_F(Switch_Class_fixture, onLock_onUnlock_HOME)
120
1
{
121
1
    RADIO_EQ_CONFIG tCfg;
122
1
    tCfg.name = "cyniu";
123
1
    tCfg.ID = "8899";
124
1
    tCfg.lock =  "ON";
125
1
126
1
    auto testRadioS = static_cast<RADIO_SWITCH*>(test_rec->getEqPointer("C"));
127
1
    testRadioS->setCode(tCfg);
128
1
    testRadioS->onLockHome();
129
1
    std::string eventStr = test_my_data.myEventHandler.run("iDom")->getEvent();
130
1
    EXPECT_THAT(eventStr, testing::HasSubstr("cyniu ON due to 433MHz button pressed"));
131
1
132
1
    tCfg.lock =  "OFF";
133
1
    testRadioS->setCode(tCfg);
134
1
    testRadioS->onLockHome();
135
1
    eventStr = test_my_data.myEventHandler.run("iDom")->getEvent();
136
1
    EXPECT_THAT(eventStr, testing::HasSubstr("cyniu OFF due to 433MHz button pressed"));
137
1
138
1
    ////////////////////// unlock
139
1
    tCfg.unlock =  "ON";
140
1
141
1
    testRadioS->setCode(tCfg);
142
1
    testRadioS->onUnlockHome();
143
1
     eventStr = test_my_data.myEventHandler.run("iDom")->getEvent();
144
1
    EXPECT_THAT(eventStr, testing::HasSubstr("cyniu ON due to 433MHz button pressed"));
145
1
146
1
    tCfg.unlock =  "OFF";
147
1
    testRadioS->setCode(tCfg);
148
1
    testRadioS->onUnlockHome();
149
1
    eventStr = test_my_data.myEventHandler.run("iDom")->getEvent();
150
    EXPECT_THAT(eventStr, testing::HasSubstr("cyniu OFF due to 433MHz button pressed"));
151
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/blockQueue/blockqueue.cpp
Line
Count
Source
1
#include "blockqueue.h"
2
#include "../iDom_server_OOP.h"
3
4
blockQueue::blockQueue()
5
130
{
6
130
}
7
std::mutex blockQueue::mutex_queue_char;
8
std::queue <MPD_COMMAND> blockQueue::_MPD_CommandQ;
9
void blockQueue::_add(MPD_COMMAND X)
10
69
{
11
69
    std::lock_guard <std::mutex> lock (mutex_queue_char);
12
69
    if(_MPD_CommandQ.size() < 10)
13
68
    {
14
68
        _MPD_CommandQ.push(X);
15
68
    }
16
1
    else
17
1
    {
18
1
        log_file_mutex.mutex_lock();
19
1
        log_file_cout << DEBUG << "za dużo danych w kolejce- nie dodaje "<< std::endl;
20
1
        log_file_mutex.mutex_unlock();
21
1
22
1
#ifdef BT_TEST
23
1
        std::string e = "za duzo w kolejce";
24
1
        throw e;
25
1
#endif
26
1
    }
27
68
}
28
29
MPD_COMMAND blockQueue::_get( )
30
50
{
31
50
    MPD_COMMAND temp = MPD_COMMAND::NULL_;
32
50
    std::lock_guard <std::mutex> lock (mutex_queue_char);
33
50
    if (_MPD_CommandQ.empty() == false){
34
47
        temp = _MPD_CommandQ.front();
35
47
        _MPD_CommandQ.pop();
36
47
    }
37
50
    return temp;
38
50
}
39
40
int blockQueue::_size()
41
38.8M
{
42
38.8M
    std::lock_guard <std::mutex> lock (mutex_queue_char);
43
38.8M
    return static_cast<int>(_MPD_CommandQ.size());
44
38.8M
}
45
46
void blockQueue::_clearAll()
47
65
{
48
65
     std::lock_guard <std::mutex> lock (mutex_queue_char);
49
82
     while (_MPD_CommandQ.empty() == false){
50
17
         _MPD_CommandQ.pop();
51
17
     }
52
65
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/THERMOMETER_CONTAINER/test/thermometer_container_BT.cpp
Line
Count
Source
1
#include <gtest/gtest.h>
2
#include <gmock/gmock.h>
3
#include "../../iDomTools/test/iDomTools_fixture.h"
4
#include "../thermometer_container.h"
5
6
class Thermometer_container_fixture :  public ::testing::Test //public iDomTOOLS_ClassTest
7
{
8
public:
9
    THERMOMETER_CONTAINER testThermo;
10
    std::string termoName = "test_thermometer";
11
    std::vector<std::string> v;
12
13
    void SetUp() final
14
4
    {
15
4
        std::vector<std::string> v = {"10.2","11.22"};
16
4
        testThermo.add("inside");
17
4
        testThermo.add("outside");
18
4
        testThermo.updateAll(&v);
19
4
        v = {"20.2","21.22"};
20
4
        testThermo.updateAll(&v);
21
4
        std::cout << "temepratura inside" << testThermo.getTemp("inside") << std::endl;
22
4
        std::cout << "temepratura outside" << testThermo.getTemp("outside") << std::endl;
23
4
        testThermo.updateStats("inside");
24
4
        testThermo.updateStats("outside");
25
4
        std::cout << "rozmiar mapy termoetrow: " << testThermo.sizeOf() << std::endl;
26
4
        testThermo.showAll();
27
4
        puts("SetUp() Thermometer_container_fixture");
28
4
        puts("--------------------------------------");
29
4
    }
30
};
31
TEST_F(Thermometer_container_fixture, returnUnexistPTR)
32
1
{
33
1
    EXPECT_THROW(testThermo.returnThermometerPtr("fake"),std::string);
34
1
}
35
36
TEST_F(Thermometer_container_fixture, getStatsByName)
37
1
{
38
1
    std::string returnedStr = testThermo.getStatsByName("inside");
39
1
    std::cout << "zwrocono " << returnedStr << std::endl;
40
1
    EXPECT_THAT(returnedStr, testing::HasSubstr("min: 20.2"));
41
1
    EXPECT_THAT(returnedStr, testing::HasSubstr("max: 20.2"));
42
1
}
43
44
TEST_F(Thermometer_container_fixture, getLast2)
45
1
{
46
1
    std::cout << "rozmiar mapy termoetrow: " << testThermo.sizeOf() << std::endl;
47
1
    testThermo.updateStats("inside");
48
1
    testThermo.updateStats("outside");
49
1
    testThermo.showAll();
50
1
    v = {"44.4","45.45"};
51
1
    testThermo.updateAll(&v);
52
1
    testThermo.updateStats("inside");
53
1
    testThermo.updateStats("outside");
54
1
    std::string returnedStr = testThermo.getStatsByName("inside");
55
1
    std::cout << "zwrocono " << returnedStr <<"||"<< std::endl;
56
1
    auto v = testThermo.getLast2("inside");
57
1
    EXPECT_EQ(v.first, 20.2);
58
1
    EXPECT_EQ(v.second, 44.4);
59
1
}
60
61
TEST_F(Thermometer_container_fixture, isMoreDiff)
62
1
{
63
1
    std::cout << "rozmiar mapy termoetrow: " << testThermo.sizeOf() << std::endl;
64
1
    testThermo.updateStats("inside");
65
1
    testThermo.updateStats("outside");
66
1
    testThermo.showAll();
67
1
    v = {"24.4","45.45"};
68
1
    testThermo.updateAll(&v);
69
1
    testThermo.updateStats("inside");
70
1
    testThermo.updateStats("outside");
71
1
    EXPECT_FALSE(testThermo.isMoreDiff("inside",15.5));
72
    EXPECT_TRUE(testThermo.isMoreDiff("outside",15.5));
73
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/blockQueue/test/blockqueue_BT.cpp
Line
Count
Source
1
#include <gtest/gtest.h>
2
#include "../blockqueue.h"
3
#include <thread>
4
#include <iostream>
5
6
class blockQueue_Class_fixture : public ::testing::Test
7
{
8
public:
9
4
    blockQueue_Class_fixture()  {  }
10
11
protected:
12
    blockQueue test_q;
13
14
    void SetUp() final
15
4
    {
16
4
        test_q._clearAll();
17
4
        std::cout << "blockQueue_Class_fixture SetUp" << std::endl;
18
4
    }
19
20
    void TearDown() final
21
4
    {
22
4
        std::cout << "blockQueue_Class_fixture TearDown" << std::endl;
23
4
    }
24
    static void getFromQ_thread()
25
1
    {
26
1
        blockQueue q;
27
67.7k
        while(q._size() == 0 )
28
67.7k
        {
29
67.7k
        }
30
1
        EXPECT_EQ(q._get(), MPD_COMMAND::STOP);
31
38.8M
        while(q._size() == 0 )
32
38.8M
        {
33
38.8M
        }
34
1
        EXPECT_EQ(q._get(), MPD_COMMAND::STOP);
35
1
    }
36
37
    static void putToQ_thread(MPD_COMMAND c)
38
1
    {
39
1
        blockQueue q;
40
1
        q._add(c);
41
1
        sleep(1);
42
1
        q._add(c);
43
1
    }
44
};
45
46
TEST_F(blockQueue_Class_fixture, main)
47
1
{
48
1
    test_q._clearAll();
49
1
    EXPECT_EQ(test_q._size(), 0);
50
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::NULL_);
51
1
    test_q._add(MPD_COMMAND::PLAY);
52
1
    EXPECT_EQ(test_q._size(), 1);
53
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::PLAY);
54
1
    EXPECT_EQ(test_q._size(), 0);
55
1
}
56
57
TEST_F(blockQueue_Class_fixture, inThread)
58
1
{
59
1
    std::thread get(blockQueue_Class_fixture::getFromQ_thread);
60
1
    std::thread put(blockQueue_Class_fixture::putToQ_thread,MPD_COMMAND::STOP);
61
1
    get.join();
62
1
    put.join();
63
1
}
64
65
TEST_F(blockQueue_Class_fixture, allClear)
66
1
{
67
1
    EXPECT_EQ(test_q._size(), 0);
68
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::NULL_);
69
1
    test_q._add(MPD_COMMAND::PLAY);
70
1
    EXPECT_EQ(test_q._size(), 1);
71
1
    test_q._add(MPD_COMMAND::PLAY);
72
1
    EXPECT_EQ(test_q._size(), 2);
73
1
    test_q._clearAll();
74
1
    EXPECT_EQ(test_q._size(), 0);
75
1
}
76
77
TEST_F(blockQueue_Class_fixture, capacityExceeded)
78
1
{
79
1
    EXPECT_EQ(test_q._size(), 0);
80
1
81
11
    for (auto i = 0 ; i <10 ; ++i)
82
10
    {
83
10
      test_q._add(MPD_COMMAND::PLAY);
84
10
    }
85
1
86
1
    EXPECT_THROW(test_q._add(MPD_COMMAND::PLAY), std::string );
87
1
    test_q._clearAll();
88
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/THERMOMETER_CONTAINER/thermometer_container.cpp
Line
Count
Source
1
#include "thermometer_container.h"
2
3
THERMOMETER *THERMOMETER_CONTAINER::returnThermometerPtr(const std::string& name)
4
308
{
5
308
    auto m = thermoMap.find(name);
6
308
    if (m != thermoMap.end())
7
308
        return &(m->second);
8
308
    else
9
308
    {
10
2
      throw std::string("thermometer not found!");
11
2
    }
12
308
}
13
14
THERMOMETER_CONTAINER::THERMOMETER_CONTAINER()
15
388
{
16
388
}
17
18
THERMOMETER::THERMOMETER(int iter):m_stats(iter)
19
776
{
20
776
}
21
22
void THERMOMETER_CONTAINER::add(const std::string &name)
23
776
{
24
776
    auto pair = std::make_pair(name, THERMOMETER(15));
25
776
    thermoMap.insert(pair);
26
776
}
27
28
void THERMOMETER_CONTAINER::setTemp(const std::string &name, double value)
29
48
{
30
48
    returnThermometerPtr(name)->m_thermometer.oldTemp = returnThermometerPtr(name)->m_thermometer.newTemp;
31
48
    returnThermometerPtr(name)->m_thermometer.newTemp = value;
32
48
}
33
34
double THERMOMETER_CONTAINER::getTemp(const std::string &name)
35
24
{
36
24
    return returnThermometerPtr(name)->m_thermometer.newTemp;
37
24
}
38
39
double THERMOMETER_CONTAINER::getOldTemp(const std::string &name)
40
16
{
41
16
    return returnThermometerPtr(name)->m_thermometer.oldTemp;
42
16
}
43
44
TEMPERATURE_STATE THERMOMETER_CONTAINER::getLastState(const std::string &name)
45
28
{
46
28
    return returnThermometerPtr(name)->m_thermometer.lastState;
47
28
}
48
49
void THERMOMETER_CONTAINER::setState(const std::string &name, TEMPERATURE_STATE state)
50
16
{
51
16
    returnThermometerPtr(name)->m_thermometer.lastState = state;
52
16
}
53
54
void THERMOMETER_CONTAINER::updateAll(std::vector<std::string> *vectorThermo)
55
24
{
56
24
    std::string in  = vectorThermo->at(0);
57
24
    std::string out = vectorThermo->at(1);
58
24
    setTemp("inside", std::stod(in));
59
24
    setTemp("outside",std::stod(out));
60
24
}
61
62
void THERMOMETER_CONTAINER::updateStats(const std::string &name)
63
28
{
64
28
    returnThermometerPtr(name)->m_stats.push_back(returnThermometerPtr(name)->m_thermometer.newTemp);
65
28
}
66
67
std::string THERMOMETER_CONTAINER::getStatsByName(const std::string &name)
68
4
{
69
4
    return returnThermometerPtr(name)->m_stats.stats();
70
4
}
71
72
bool THERMOMETER_CONTAINER::isMoreDiff(const std::string &name, double diff)
73
14
{
74
14
    return returnThermometerPtr(name)->m_stats.isMoreDiff(diff);
75
14
}
76
77
std::pair<double, double> THERMOMETER_CONTAINER::getLast2(const std::string &name)
78
5
{
79
5
    return returnThermometerPtr(name)->m_stats.getLast2();
80
5
}
81
82
int THERMOMETER_CONTAINER::sizeOf()
83
6
{
84
6
    return static_cast<int>(thermoMap.size());
85
6
}
86
87
void THERMOMETER_CONTAINER::showAll()
88
6
{
89
6
    for(auto n : thermoMap)
90
12
    {
91
12
        std::cout << n.first << " ";
92
12
    }
93
6
    std::cout << std::endl << "koniec prointowania w " << std::endl;
94
6
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/c_connection/c_connection.cpp
Line
Count
Source (jump to first uncovered line)
1
#include <iostream>
2
#include "c_connection.h"
3
4
C_connection::C_connection (thread_data *my_data):c_socket(my_data->s_client_sock),
5
    c_from(my_data->from),recv_size(0)
6
8
{
7
8
    this -> pointer = &my_data->pointer;
8
8
    this -> my_data = my_data;
9
8
    this->m_encrypted = my_data->server_settings->encrypted;
10
8
    std::fill(std::begin(c_buffer),std::end(c_buffer),',');
11
8
    onStartConnection();
12
8
}
13
14
C_connection::~C_connection()
15
8
{
16
8
    if( mainCommandHandler != std::nullptr_t())
17
3
    {
18
3
        my_data->mainLCD->set_print_song_state(0);
19
3
        my_data->mainLCD->set_lcd_STATE(2);
20
3
        delete mainCommandHandler;
21
3
    }
22
8
    my_data->mainLCD->set_print_song_state(0);
23
8
    my_data->mainLCD->set_lcd_STATE(2);
24
8
25
8
    useful_F::sleep(3);
26
8
27
8
    shutdown(c_socket, SHUT_RDWR );
28
8
    useful_F::clearThreadArray(my_data);
29
8
    puts("C_connection::~C_connection()");
30
8
}
31
32
int C_connection::c_send(int para)
33
1
{
34
1
    crypto(str_buf,m_encriptionKey,m_encrypted); //BUG - naprawic czytanie flagi z parametru klasy
35
1
    std::string len = std::to_string( str_buf.size());
36
1
    crypto(len,m_encriptionKey,m_encrypted);
37
1
    if(( send( c_socket, len.c_str() ,len.length(), para ) ) <= 0 )
38
1
    {
39
1
        return -1;
40
1
    }
41
0
    recv_size = recv( c_socket, c_buffer , MAX_buf, para );
42
0
43
0
    if(recv_size < 0 )
44
0
    {
45
0
        log_file_mutex.mutex_lock();
46
0
        log_file_cout << ERROR << "C_connection::c_send(int para) recv() error - " << strerror( errno ) << std::endl;
47
0
        log_file_mutex.mutex_unlock();
48
0
        return -1;
49
0
    }
50
0
    else if (recv_size == 0)
51
0
    {
52
0
        return -1;
53
0
    }
54
0
55
0
    auto len_send = str_buf.length();
56
0
57
0
    while (len_send > 0)
58
0
    {
59
0
        auto len_temp = send( c_socket, str_buf.c_str() ,str_buf.length(), para );
60
0
        if(len_temp <= 0 )
61
0
        {
62
0
            return -1;
63
0
        }
64
0
        len_send -= len_temp;
65
0
        str_buf.erase(0,len_temp);
66
0
    }
67
0
    return 0;
68
0
}
69
70
int C_connection::c_send(const std::string &command )
71
1
{
72
1
    str_buf = command;
73
1
    return c_send(0);
74
1
}
75
76
int C_connection::c_recv(int para)
77
1
{
78
1
    struct timeval tv;
79
1
    tv.tv_sec = 90;
80
1
    tv.tv_usec = 0;
81
1
    setsockopt(c_socket,SOL_SOCKET,SO_RCVTIMEO,(char*)&tv , sizeof(struct timeval));
82
1
83
1
    recv_size = recv(c_socket, c_buffer, MAX_buf, para);
84
1
85
1
    if(recv_size < 0)
86
1
    {
87
1
        log_file_mutex.mutex_lock();
88
1
        log_file_cout << ERROR << "C_connection::c_recv(int para) recv() error - " << strerror( errno ) << std::endl;
89
1
        log_file_mutex.mutex_unlock();
90
1
        return -1;
91
1
    }
92
0
    else if (recv_size == 0)
93
0
    {
94
0
        return -1;
95
0
    }
96
0
    return recv_size;
97
0
}
98
99
void C_connection::c_analyse(int recvSize)
100
3
{
101
3
    std::string buf;
102
3
103
3
    buf = c_read_buf(recvSize);
104
3
    my_data->myEventHandler.run("command")->addEvent(buf);
105
3
    std::vector <std::string> command;
106
3
    try{
107
3
    useful_F::tokenizer(command," \n,", buf);
108
3
    }
109
3
    catch (std::string& k){
110
1
        log_file_mutex.mutex_lock();
111
1
        log_file_cout << DEBUG << "brak komendy - " << k << std::endl;
112
1
        log_file_mutex.mutex_unlock();
113
1
        str_buf = "empty command";
114
1
        return;
115
1
    }
116
2
117
2
#ifdef BT_TEST
118
2
    std::cout << "komenda: " << str_buf << " command.size() " << command.size() << std::endl;
119
2
#endif
120
2
    str_buf = "unknown command\n";
121
2
122
2
    for(std::string t : command)
123
5
    {
124
5
        str_buf += t+" ";
125
5
    }
126
2
127
2
    str_buf = mainCommandHandler->run(command,my_data);
128
2
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDom_server_OOP.h
Line
Count
Source
1
#ifndef GLOBAL_H
2
#define GLOBAL_H
3
4
#include <iostream>
5
#include <fstream>
6
#include <string>
7
#include <cstdlib>
8
#include <pthread.h>
9
#include <stdio.h>
10
#include <stdlib.h>
11
#include <sys/socket.h>
12
#include <sys/types.h>
13
#include <netinet/in.h>
14
#include <vector>
15
#include <thread>
16
#include <arpa/inet.h>
17
#include <netinet/in.h>
18
#include <unistd.h>
19
#include <sys/fcntl.h>
20
#include <unistd.h>
21
#include <errno.h>
22
#include <signal.h>
23
#include <time.h>
24
#include <wiringPi.h>
25
#include <chrono>
26
#include <array>
27
28
// MOJE BIBLIOTEKI
29
#include "KEY/key.h"
30
#include "logger/logger.hpp"
31
#include "files_tree/files_tree.h"
32
#include "menu_tree/menu_tree.h"
33
#include "LCD_c/lcd_c.h"
34
#include "command/command.h"
35
#include "../libs/event_counters/event_counters_handler.h"
36
#include "iDomTools/idomtools.h"
37
#include "iDomStatus/idomstatus.h"
38
#include "iDomSaveState/idom_save_state.h"
39
40
4
#define log_file_cout  f_log //std::cout zmien f_log na std::cout i bedzie wypisywac na ekran
41
2
#define log_file_mutex f_log
42
43
enum class iDomStateEnum{
44
    CLOSE = 0,
45
    RELOAD,
46
    ERROR,
47
    WORKING,
48
    HARD_RELOAD
49
};
50
51
namespace iDomConst
52
{
53
constexpr int MAX_CONNECTION = 10;
54
constexpr int FREE  = 1;
55
constexpr int RS232 = 11;
56
constexpr int CLOCK = 12;
57
constexpr int ok    = 0;
58
constexpr int GPIO_SPIK = 21;
59
constexpr int GPIO_PRINTER = 22;
60
constexpr int BUTTON_PIN = 25;
61
}
62
struct ALERT
63
{
64
    Clock time;
65
    STATE state = STATE::DEACTIVE;
66
    unsigned int fromVolume = 48;
67
    unsigned int toVolume = 58;
68
    unsigned int radioID = 8;
69
};
70
71
extern std::string _logfile;
72
extern Logger log_file_mutex;
73
extern std::string buffer;
74
75
enum class TEMPERATURE_STATE;
76
enum class PILOT_KEY;
77
78
struct MPD_info{
79
    std::string title   = "NULL";
80
    std::string radio   = "NULL";
81
    std::string artist  = "NULL";
82
    int volume = 0;
83
    bool isPlay = false;
84
    int currentSongID = 0;
85
    std::vector <std::string> songList = {"NULL"};
86
};
87
struct s_pointer{
88
    unsigned int *ptr_who;
89
    int32_t *ptr_buf;
90
};
91
92
struct Thread_array_struc {
93
    std::thread thread;
94
    std::thread::id thread_ID = std::thread::id(0);
95
    std::string thread_name;
96
    int thread_socket = 0;
97
};
98
99
struct address_another_servers {
100
    int id;
101
    std::string SERVER_IP;
102
};
103
104
struct FTP_SERVER{
105
    std::string URL;
106
    std::string user;
107
    std::string pass;
108
};
109
struct iDOM_STATE{
110
    STATE houseState = STATE::UNDEFINE;
111
112
};
113
114
struct config{
115
    std::string portRS232;
116
    std::string portRS232_clock;
117
    std::string BaudRate;
118
    std::string RFLinkPort;
119
    std::string RFLinkBaudRate;
120
    int PORT;
121
    std::string SERVER_IP;
122
    std::string MPD_IP;
123
    std::string MOVIES_DB_PATH;
124
    std::string MENU_PATH;
125
    std::string THREAD_MPD   = "NULL";
126
    std::string THREAD_IRDA  = "NULL";
127
    std::string THREAD_CRON  = "NULL";
128
    std::string THREAD_RS232 = "NULL";
129
    std::string THREAD_DUMMY = "NULL";
130
    std::string TS_KEY= " gg ";
131
    std::string cameraLedON = "";
132
    std::string cameraLedOFF ="";
133
    std::string cameraURL="";
134
    std::string facebookAccessToken = "";
135
    std::string viberToken = "NULL";
136
    std::string viberAvatar;
137
    std::vector <std::string> viberReceiver;
138
    std::string viberSender;
139
    std::string radio433MHzConfigFile;
140
    std::string omxplayerFile = "NULL";
141
    int ID_server = 0;
142
    int v_delay;
143
    bool encrypted = true;
144
145
    FTP_SERVER ftpServer;
146
    std::string lightningApiURL = "NULL";
147
    std::string saveFilePath = "NULL";
148
};
149
150
struct LED_Strip{
151
    std::string from;
152
    std::string to;
153
    std::string R;
154
    std::string G;
155
    std::string B;
156
    std::string colorName;
157
158
    LED_Strip (int from, int to, int r, int g, int b, std::string colorName = "NULL"):from(std::to_string(from)),
159
        to(std::to_string(to)),
160
        R(std::to_string(r)),
161
        G(std::to_string(g)),
162
        B(std::to_string(b)),
163
        colorName(colorName)
164
    {
165
166
    }
167
    LED_Strip (const std::string& from,
168
               const std::string& to,
169
               const std::string& r,
170
               const std::string& g,
171
               const std::string& b,
172
               const std::string& colorName = "NULL"):
173
        from(from),
174
        to(to),
175
        R(r),
176
        G(g),
177
        B(b),
178
        colorName(colorName)
179
    {
180
181
    }
182
183
    void set (const std::string& from,
184
              const std::string& to,
185
              const std::string& r,
186
              const std::string& g,
187
              const std::string& b,
188
              const std::string& colorName = "NULL")
189
    {
190
        this->from =from;
191
        this->to = to;
192
        R = r;
193
        G = g;
194
        B = b;
195
        this->colorName =colorName;
196
    }
197
198
    void set (int from, int to, int r, int g, int b, std::string colorName = "NULL"){
199
        this->from = std::to_string(from);
200
        this->to = std::to_string(to);
201
        R = std::to_string(r);
202
        G = std::to_string(g);
203
        B = std::to_string(b);
204
        this->colorName =colorName;
205
    }
206
207
    std::string getColorName() const{
208
        return colorName;
209
    }
210
211
    std::string get(unsigned int _from, unsigned int _to) const{
212
        if (_from != 0 || _to != 60){
213
            return "LED:["+std::to_string(_from)+"-"+std::to_string(_to)+"-"+R+"-"+G+"-"+B+"];";
214
        }
215
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
216
    }
217
218
    std::string makeCommand(const std::string& from,
219
                            const std::string& to,
220
                            const std::string& R,
221
                            const std::string& G,
222
                            const std::string& B){
223
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
224
    }
225
};
226
227
struct pilot_led{
228
    unsigned int counter=0;
229
    std::vector<LED_Strip> colorLED   = { LED_Strip(1,60,237,145,33 ,"carrot orange"),
230
                                          LED_Strip(1,60,255,0,0    ,"red"),
231
                                          LED_Strip(1,60,0,255,0    ,"green"),
232
                                          LED_Strip(1,60,0,0,255    ,"blue"),
233
                                          LED_Strip(1,60,255,255,255,"white"),
234
                                          LED_Strip(1,60,255,255,0  ,"yellow"),
235
                                          LED_Strip(1,60,0,255,255  ,"cyan"),
236
                                          LED_Strip(1,60,255,0,255  ,"magenta")
237
                                        };
238
};
239
240
class command; // for struc thread_data req
241
class iDomTOOLS;
242
class RADIO_EQ_CONTAINER;
243
class RFLinkHandler;
244
245
struct thread_data{
246
    int s_client_sock;
247
    struct sockaddr_in from;
248
    struct config *server_settings = NULL;
249
    struct s_pointer pointer;
250
    LCD_c *mainLCD = NULL;
251
    files_tree *main_tree = NULL;
252
    menu_tree *main_MENU = NULL;
253
    iDomTOOLS *main_iDomTools = NULL;
254
    RFLinkHandler *main_RFLink = NULL;
255
    std::array<Thread_array_struc, iDomConst::MAX_CONNECTION> *main_THREAD_arr = NULL;
256
    time_t start;
257
    time_t now_time;
258
    int sleeper;
259
    std::map <std::string, std::unique_ptr <KEY> > key_map;
260
    MPD_info *ptr_MPD_info = NULL;
261
    pilot_led * ptr_pilot_led = NULL;
262
    std::map <std::string, std::unique_ptr<command> >* commandMapPtr = NULL;
263
    event_counters_handler myEventHandler;
264
    std::string encriptionKey = "40%";
265
    iDomSTATUS *main_iDomStatus;
266
    iDOM_STATE idom_all_state;
267
    ALERT alarmTime;
268
    std::shared_ptr<RADIO_EQ_CONTAINER> main_REC;
269
    iDomStateEnum iDomProgramState = iDomStateEnum::WORKING;
270
};
271
272
struct thread_data_rs232{
273
    std::string portRS232;
274
    std::string portRS232_clock;
275
    std::string BaudRate;
276
    struct s_pointer pointer;
277
};
278
279
#endif // GLOBAL_H
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/c_connection/c_connection.h
Line
Count
Source
1
#ifndef C_CONNECTION_H
2
#define C_CONNECTION_H
3
#include <mutex>
4
#include <unistd.h>
5
#include <iostream>
6
#include "../functions/functions.h"
7
#include "../CRON/cron.hpp"
8
#include "../functions/mpd_cli.h"
9
#include "../command/commandhandlerroot.h"
10
#include "../iDom_server_OOP.h"
11
12
constexpr int MAX_buf = 32768;
13
14
class C_connection
15
{
16
#ifdef BT_TEST
17
   friend class c_connection_fixture;
18
#endif
19
public:
20
    C_connection(thread_data *my_data);
21
    ~C_connection();
22
23
    thread_data *my_data;
24
    int c_socket;
25
    sockaddr_in c_from;
26
27
    char c_buffer[MAX_buf];
28
    int recv_size;
29
    struct s_pointer *pointer;
30
31
    int c_send(int para);
32
    int c_send(const std::string& command);
33
    int c_recv(int para);
34
    std::string c_read_buf(int recvSize);
35
    void c_analyse(int recvSize);
36
    void setEncriptionKey(const std::string& key);
37
    void setEncrypted(bool flag);
38
    commandHandler *mainCommandHandler = NULL;
39
    void onStartConnection();
40
    void onStopConnection();
41
    void cryptoLog(std::string &toEncrypt);
42
#ifdef BT_TEST
43
1
    std::string getStr_buf(){
44
1
        return str_buf;
45
1
    }
46
#endif
47
private:
48
    std::string str_buf;
49
    blockQueue char_queue;
50
    int counter = 0;
51
    std::string m_encriptionKey;
52
    bool m_encrypted;
53
    void crypto(std::string &toEncrypt, std::string key, bool encrypted);
54
};
55
56
#endif // C_CONNECTION_H
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/blockQueue/blockqueue.cpp
Line
Count
Source
1
#include "blockqueue.h"
2
#include "../iDom_server_OOP.h"
3
4
blockQueue::blockQueue()
5
130
{
6
130
}
7
std::mutex blockQueue::mutex_queue_char;
8
std::queue <MPD_COMMAND> blockQueue::_MPD_CommandQ;
9
void blockQueue::_add(MPD_COMMAND X)
10
69
{
11
69
    std::lock_guard <std::mutex> lock (mutex_queue_char);
12
69
    if(_MPD_CommandQ.size() < 10)
13
69
    {
14
68
        _MPD_CommandQ.push(X);
15
68
    }
16
69
    else
17
69
    {
18
1
        log_file_mutex.mutex_lock();
19
1
        log_file_cout << DEBUG << "za dużo danych w kolejce- nie dodaje "<< std::endl;
20
1
        log_file_mutex.mutex_unlock();
21
1
22
1
#ifdef BT_TEST
23
1
        std::string e = "za duzo w kolejce";
24
1
        throw e;
25
1
#endif
26
1
    }
27
69
}
28
29
MPD_COMMAND blockQueue::_get( )
30
50
{
31
50
    MPD_COMMAND temp = MPD_COMMAND::NULL_;
32
50
    std::lock_guard <std::mutex> lock (mutex_queue_char);
33
50
    if (_MPD_CommandQ.empty() == false){
34
47
        temp = _MPD_CommandQ.front();
35
47
        _MPD_CommandQ.pop();
36
47
    }
37
50
    return temp;
38
50
}
39
40
int blockQueue::_size()
41
32.9M
{
42
32.9M
    std::lock_guard <std::mutex> lock (mutex_queue_char);
43
32.9M
    return static_cast<int>(_MPD_CommandQ.size());
44
32.9M
}
45
46
void blockQueue::_clearAll()
47
65
{
48
65
     std::lock_guard <std::mutex> lock (mutex_queue_char);
49
82
     while (_MPD_CommandQ.empty() == false){
50
17
         _MPD_CommandQ.pop();
51
17
     }
52
65
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/c_connection/c_connection2.cpp
Line
Count
Source
1
#include "c_connection.h"
2
#include <iostream>
3
4
std::string C_connection::c_read_buf (int recvSize)
5
3
{
6
3
    std::string str_buf;
7
34
    for (int i = 0; i < recvSize; ++i)
8
31
    {
9
31
        str_buf.push_back( c_buffer[i]);
10
31
    }
11
3
    crypto(str_buf,m_encriptionKey,m_encrypted);
12
3
    return str_buf;
13
3
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/blockQueue/test/blockqueue_BT.cpp
Line
Count
Source
1
#include <gtest/gtest.h>
2
#include "../blockqueue.h"
3
#include <thread>
4
#include <iostream>
5
6
class blockQueue_Class_fixture : public ::testing::Test
7
{
8
public:
9
4
    blockQueue_Class_fixture()  {  }
10
11
protected:
12
    blockQueue test_q;
13
14
    void SetUp() final
15
4
    {
16
4
        test_q._clearAll();
17
4
        std::cout << "blockQueue_Class_fixture SetUp" << std::endl;
18
4
    }
19
20
    void TearDown() final
21
4
    {
22
4
        std::cout << "blockQueue_Class_fixture TearDown" << std::endl;
23
4
    }
24
    static void getFromQ_thread()
25
1
    {
26
1
        blockQueue q;
27
6.36k
        while(q._size() == 0 )
28
6.36k
        {
29
6.36k
        }
30
1
        EXPECT_EQ(q._get(), MPD_COMMAND::STOP);
31
32.9M
        while(q._size() == 0 )
32
32.9M
        {
33
32.9M
        }
34
1
        EXPECT_EQ(q._get(), MPD_COMMAND::STOP);
35
1
    }
36
37
    static void putToQ_thread(MPD_COMMAND c)
38
1
    {
39
1
        blockQueue q;
40
1
        q._add(c);
41
1
        sleep(1);
42
1
        q._add(c);
43
1
    }
44
};
45
46
TEST_F(blockQueue_Class_fixture, main)
47
1
{
48
1
    test_q._clearAll();
49
1
    EXPECT_EQ(test_q._size(), 0);
50
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::NULL_);
51
1
    test_q._add(MPD_COMMAND::PLAY);
52
1
    EXPECT_EQ(test_q._size(), 1);
53
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::PLAY);
54
1
    EXPECT_EQ(test_q._size(), 0);
55
1
}
56
57
TEST_F(blockQueue_Class_fixture, inThread)
58
1
{
59
1
    std::thread get(blockQueue_Class_fixture::getFromQ_thread);
60
1
    std::thread put(blockQueue_Class_fixture::putToQ_thread,MPD_COMMAND::STOP);
61
1
    get.join();
62
1
    put.join();
63
1
}
64
65
TEST_F(blockQueue_Class_fixture, allClear)
66
1
{
67
1
    EXPECT_EQ(test_q._size(), 0);
68
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::NULL_);
69
1
    test_q._add(MPD_COMMAND::PLAY);
70
1
    EXPECT_EQ(test_q._size(), 1);
71
1
    test_q._add(MPD_COMMAND::PLAY);
72
1
    EXPECT_EQ(test_q._size(), 2);
73
1
    test_q._clearAll();
74
1
    EXPECT_EQ(test_q._size(), 0);
75
1
}
76
77
TEST_F(blockQueue_Class_fixture, capacityExceeded)
78
1
{
79
1
    EXPECT_EQ(test_q._size(), 0);
80
1
81
11
    for (auto i = 0 ; i <10 ; ++i)
82
10
    {
83
10
      test_q._add(MPD_COMMAND::PLAY);
84
10
    }
85
1
86
    EXPECT_THROW(test_q._add(MPD_COMMAND::PLAY), std::string );
87
    test_q._clearAll();
88
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/c_connection/c_connection_node.cpp
Line
Count
Source
1
2
#include "c_connection.h"
3
#include <iostream>
4
5
//////// not used now
6
//void C_connection::c_start_master ()
7
//{
8
//    std::cout << " w pamieci jest " <<my_data->server_settings->AAS.size() <<" nodow\n";
9
//    for (unsigned int i =0; i<my_data->server_settings->AAS.size(); ++i )
10
//    {
11
//        std::cout << " jest ustawien id " << my_data->server_settings->AAS[i].id << std::endl;
12
//        std::cout << " jest ustawien ip " << my_data->server_settings->AAS[i].SERVER_IP << std::endl;
13
//    }
14
//        while (1)
15
//        {
16
//             //c_recv_master_to();
17
//             c_recv_send_master();
18
//             std::cout << " odebralem w masterze \n";
19
//             //c_send_master_to(c_bufor_tmp[16]);
20
//        }
21
//}
22
23
24
//void C_connection::c_recv_send_master()
25
//{
26
//    while (1)
27
//    {
28
//        std::this_thread::sleep_for( std::chrono::milliseconds(50) );
29
30
//        mutex_who.lock();
31
//        if (pointer->ptr_who[0] == my_data->server_settings->ID_server)
32
//        {
33
//            mutex_buf.lock();
34
35
//            for (int i =0; i < MAX_MSG_LEN; ++i )
36
//            {
37
//                 pointer->ptr_buf[i]-=1;
38
//            }
39
//            pointer->ptr_who[0] = pointer->ptr_who[1];
40
//            pointer->ptr_who[1] = my_data->server_settings->ID_server;
41
//            mutex_buf.unlock();
42
//        }
43
//         mutex_who.unlock();
44
//    } // end while
45
//}
46
47
void C_connection::setEncriptionKey(const std::string& key)
48
1
{
49
1
    m_encriptionKey = key;
50
1
}
51
52
void C_connection::setEncrypted(bool flag)
53
4
{
54
4
    m_encrypted = flag;
55
4
}
56
57
void C_connection::crypto(std::string &toEncrypt, std::string key, bool encrypted)
58
9
{
59
9
    if (!encrypted){
60
5
          return;
61
5
      }
62
4
    unsigned int keySize = key.size()-1;
63
4
#ifdef BT_TEST
64
4
    std::cout << "key: " << key << " size: " << key.size() << std::endl;
65
4
#endif
66
74
    for (unsigned int i = 0; i < toEncrypt.size (); i++)
67
70
    {
68
70
        if (keySize == 0)
69
6
            keySize = key.size()-1;
70
64
        else
71
64
            --keySize;
72
70
        toEncrypt[i] ^= key[keySize];
73
70
    }
74
4
}
75
76
void C_connection::onStartConnection()
77
8
{
78
8
//    log_file_mutex.mutex_lock();
79
8
//    log_file_cout << INFO<< "konstruuje nowy obiekt do komunikacj na gniezdzie " << c_socket << std::endl;
80
8
//    log_file_mutex.mutex_unlock();
81
8
}
82
83
void C_connection::onStopConnection()
84
1
{
85
1
    my_data->main_iDomTools->cameraLedOFF(my_data->server_settings->cameraLedOFF);
86
1
}
87
88
void C_connection::cryptoLog(std::string &toEncrypt)
89
2
{
90
2
    crypto(toEncrypt,m_encriptionKey,m_encrypted);
91
2
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/logger/logger.hpp
Line
Count
Source
1
/*
2
 * logger.hpp
3
 *
4
 *
5
 * Logger Library Header
6
 *
7
 *
8
 * Copyright (C) 2013-2014  Bryant Moscon - bmoscon@gmail.com
9
 *
10
 * Permission is hereby granted, free of charge, to any person obtaining a copy
11
 * of this software and associated documentation files (the "Software"), to
12
 * deal in the Software without restriction, including without limitation the
13
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
14
 * sell copies of the Software, and to permit persons to whom the Software is
15
 * furnished to do so, subject to the following conditions:
16
 *
17
 * 1. Redistributions of source code must retain the above copyright notice,
18
 *    this list of conditions, and the following disclaimer.
19
 *
20
 * 2. Redistributions in binary form must reproduce the above copyright notice,
21
 *    this list of conditions and the following disclaimer in the documentation
22
 *    and/or other materials provided with the distribution, and in the same
23
 *    place and form as other copyright, license and disclaimer information.
24
 *
25
 * 3. The end-user documentation included with the redistribution, if any, must
26
 *    include the following acknowledgment: "This product includes software
27
 *    developed by Bryant Moscon (http://www.bryantmoscon.org/)", in the same
28
 *    place and form as other third-party acknowledgments. Alternately, this
29
 *    acknowledgment may appear in the software itself, in the same form and
30
 *    location as other such third-party acknowledgments.
31
 *
32
 * 4. Except as contained in this notice, the name of the author, Bryant Moscon,
33
 *    shall not be used in advertising or otherwise to promote the sale, use or
34
 *    other dealings in this Software without prior written authorization from
35
 *    the author.
36
 *
37
 *
38
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
41
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
42
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
44
 * THE SOFTWARE.
45
 *
46
 */
47
#ifndef __LOGGER__
48
#define __LOGGER__
49
50
#include <fstream>
51
#include <cassert>
52
#include <ctime>
53
#include <sstream>
54
55
// Log levels
56
typedef enum {
57
    US =0,
58
    VERBOSE,
59
    DEBUG,
60
    INFO,
61
    WARNING,
62
    ERROR,
63
    CRITICAL,
64
    FATAL
65
} logger_level;
66
67
class Logger : public std::ostringstream {
68
public:
69
70
    explicit Logger(const char *f);
71
    explicit Logger(const std::string& f);
72
    Logger (const Logger &);
73
    Logger &operator= (const Logger &);
74
    ~Logger();
75
    static pthread_mutex_t mutex_log;
76
77
    void set_level(const logger_level& level);
78
    void flush();
79
    void mutex_lock();
80
    void mutex_unlock();
81
82
    template <typename T>
83
    Logger& operator<<(const T& t)
84
4
    {
85
4
        *static_cast<std::ostringstream *>(this) << t;
86
4
        return (*this);
87
4
    }
_ZN6LoggerlsIPcEERS_RKT_
Line
Count
Source
84
1
    {
85
1
        *static_cast<std::ostringstream *>(this) << t;
86
1
        return (*this);
87
1
    }
_ZN6LoggerlsIA16_cEERS_RKT_
Line
Count
Source
84
3
    {
85
3
        *static_cast<std::ostringstream *>(this) << t;
86
3
        return (*this);
87
3
    }
88
89
    Logger& operator<<(const logger_level& level);
90
    typedef Logger& (* LoggerManip)(Logger&);
91
    Logger& operator<<(LoggerManip m);
92
93
private:
94
    std::string get_time() const;
95
    inline const char* level_str(const logger_level& level);
96
public:
97
    std::ofstream _file;
98
private:
99
    std::ostream& _log;
100
    logger_level _level;
101
    logger_level _line_level;
102
};
103
104
105
namespace std { 
106
inline Logger& endl(Logger& out)
107
{
108
    out.put('\n');
109
    out.flush();
110
    return (out);
111
}
112
}// end namespace std
113
114
#endif
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/c_connection/test/c_connection_BT.cpp
Line
Count
Source (jump to first uncovered line)
1
#include <gtest/gtest.h>
2
#include "../../iDomTools/test/iDomTools_fixture.h"
3
4
#include "../c_connection.h"
5
6
class c_connection_fixture : public iDomTOOLS_ClassTest
7
{
8
public:
9
8
    c_connection_fixture():test_connection(std::nullptr_t()) {
10
8
    }
11
12
protected:
13
    std::unique_ptr<C_connection> test_connection;
14
    void SetUp() final
15
8
    {
16
8
        std::cout << "c_connection_fixture SetUp()" << std::endl;
17
8
        iDomTOOLS_ClassTest::SetUp();
18
8
        test_connection = std::make_unique<C_connection>(&test_my_data);
19
8
        test_connection->m_encriptionKey = "key";
20
8
        test_connection->m_encrypted = false;
21
8
        test_connection->c_socket = 0;
22
8
    }
23
    void TearDown() final
24
8
    {
25
8
        iDomTOOLS_ClassTest::TearDown();
26
8
        std::cout << "c_connection_fixture TearDown()" << std::endl;
27
8
    }
28
    void crypto_fixture(std::string &toEncrypt, std::string key)
29
2
    {
30
2
        test_connection->crypto(toEncrypt, std::move(key), true);
31
2
    }
32
};
33
34
TEST_F(c_connection_fixture, crypto)
35
1
{
36
1
    std::string key = "210116556";
37
1
    std::string test_msg = "kokosowa ksiezniczka";
38
1
    std::string toEncrypt = test_msg;
39
1
    crypto_fixture(toEncrypt, key);
40
1
41
21
    for(int i = 0; i < toEncrypt.size(); ++i)
42
20
    {
43
40
        EXPECT_NE(test_msg[i],toEncrypt[i]) << " niestety równe: " << toEncrypt[i]
44
40
                                            << " na indeksie: " << i;
45
20
    }
46
1
    std::cout << "wiadomość: " << test_msg << " zakodowane: "<< toEncrypt << std::endl;
47
1
    crypto_fixture(toEncrypt, key);
48
1
    std::cout << "wiadomość: " << test_msg << " odkodowane: "<< toEncrypt << std::endl;
49
2
    EXPECT_STREQ(toEncrypt.c_str(), test_msg.c_str()) << "wiadomosci nie są równe";
50
1
}
51
52
TEST_F(c_connection_fixture, c_analyse)
53
1
{
54
1
    commandHandlerRoot* chr = new commandHandlerRoot(&test_my_data);
55
1
    test_connection->mainCommandHandler = chr;
56
1
    int i = 0;
57
1
    std::string strMsg = "fake command";
58
1
    for (char n : strMsg)
59
12
        test_connection->c_buffer[i++] = n;
60
1
    test_connection->setEncrypted(false);
61
1
    test_connection->c_analyse(strMsg.size());
62
1
    EXPECT_THAT(test_my_data.myEventHandler.run("command")->getEvent()
63
1
                ,testing::HasSubstr(strMsg));
64
1
}
65
66
TEST_F(c_connection_fixture, c_recv)
67
1
{
68
1
    EXPECT_EQ(-1, test_connection->c_recv(1));
69
1
}
70
71
TEST_F(c_connection_fixture, c_send)
72
1
{
73
1
    EXPECT_EQ(-1, test_connection->c_send("test"));
74
1
}
75
76
TEST_F(c_connection_fixture, cryptoLog)
77
1
{
78
1
    std::string msg("tajna wiadomosc");
79
1
    std::string msgBackup(msg);
80
1
    test_connection->setEncriptionKey("key_test");
81
1
    test_connection->setEncrypted(true);
82
1
    ///////szyfrowanie
83
1
    test_connection->cryptoLog(msg);
84
1
    EXPECT_STRNE(msgBackup.c_str(), msg.c_str());
85
1
    std::cout << "ZASZUFROWANY: " << msg << std::endl;
86
1
    ////// deszyfracja
87
1
    test_connection->cryptoLog(msg);
88
1
    EXPECT_STREQ(msgBackup.c_str(), msg.c_str());
89
1
}
90
91
TEST_F(c_connection_fixture, onStopConnection)
92
1
{
93
1
    TEST_DATA::return_httpPost = "ok.\n";
94
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("cameraLED"),STATE::UNKNOWN);
95
1
    test_connection->onStopConnection();
96
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("cameraLED"),STATE::OFF);
97
1
}
98
99
TEST_F(c_connection_fixture, exitFlow)
100
1
{
101
1
    commandHandlerRoot* chr = new commandHandlerRoot(&test_my_data);
102
1
    test_connection->mainCommandHandler = chr;
103
1
104
1
    int i = 0;
105
1
    std::string strMsg = "program stop server";
106
1
    for (char n : strMsg)
107
19
        test_connection->c_buffer[i++] = n;
108
1
    test_connection->setEncrypted(false);
109
1
    EXPECT_THROW(test_connection->c_analyse(strMsg.size()),std::string );
110
1
}
111
112
TEST_F(c_connection_fixture, emptyCommand)
113
1
{
114
1
    commandHandlerRoot* chr = new commandHandlerRoot(&test_my_data);
115
1
    test_connection->mainCommandHandler = chr;
116
1
117
1
    int i = 0;
118
1
    std::string strMsg = "";
119
1
    for (char n : strMsg)
120
0
        test_connection->c_buffer[i++] = n;
121
1
    test_connection->setEncrypted(false);
122
1
    test_connection->c_analyse(strMsg.size());
123
1
    EXPECT_STREQ(test_connection->getStr_buf().c_str(), "empty command");
124
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDom_server_OOP.h
Line
Count
Source
1
#ifndef GLOBAL_H
2
#define GLOBAL_H
3
4
#include <iostream>
5
#include <fstream>
6
#include <string>
7
#include <cstdlib>
8
#include <pthread.h>
9
#include <stdio.h>
10
#include <stdlib.h>
11
#include <sys/socket.h>
12
#include <sys/types.h>
13
#include <netinet/in.h>
14
#include <vector>
15
#include <thread>
16
#include <arpa/inet.h>
17
#include <netinet/in.h>
18
#include <unistd.h>
19
#include <sys/fcntl.h>
20
#include <unistd.h>
21
#include <errno.h>
22
#include <signal.h>
23
#include <time.h>
24
#include <wiringPi.h>
25
#include <chrono>
26
#include <array>
27
28
// MOJE BIBLIOTEKI
29
#include "KEY/key.h"
30
#include "logger/logger.hpp"
31
#include "files_tree/files_tree.h"
32
#include "menu_tree/menu_tree.h"
33
#include "LCD_c/lcd_c.h"
34
#include "command/command.h"
35
#include "../libs/event_counters/event_counters_handler.h"
36
#include "iDomTools/idomtools.h"
37
#include "iDomStatus/idomstatus.h"
38
#include "iDomSaveState/idom_save_state.h"
39
40
10
#define log_file_cout  f_log //std::cout zmien f_log na std::cout i bedzie wypisywac na ekran
41
4
#define log_file_mutex f_log
42
43
enum class iDomStateEnum{
44
    CLOSE = 0,
45
    RELOAD,
46
    ERROR,
47
    WORKING,
48
    HARD_RELOAD
49
};
50
51
namespace iDomConst
52
{
53
constexpr int MAX_CONNECTION = 10;
54
constexpr int FREE  = 1;
55
constexpr int RS232 = 11;
56
constexpr int CLOCK = 12;
57
constexpr int ok    = 0;
58
constexpr int GPIO_SPIK = 21;
59
constexpr int GPIO_PRINTER = 22;
60
constexpr int BUTTON_PIN = 25;
61
}
62
struct ALERT
63
{
64
    Clock time;
65
    STATE state = STATE::DEACTIVE;
66
    unsigned int fromVolume = 48;
67
    unsigned int toVolume = 58;
68
    unsigned int radioID = 8;
69
};
70
71
extern std::string _logfile;
72
extern Logger log_file_mutex;
73
extern std::string buffer;
74
75
enum class TEMPERATURE_STATE;
76
enum class PILOT_KEY;
77
78
struct MPD_info{
79
    std::string title   = "NULL";
80
    std::string radio   = "NULL";
81
    std::string artist  = "NULL";
82
    int volume = 0;
83
    bool isPlay = false;
84
    int currentSongID = 0;
85
    std::vector <std::string> songList = {"NULL"};
86
};
87
struct s_pointer{
88
    unsigned int *ptr_who;
89
    int32_t *ptr_buf;
90
};
91
92
struct Thread_array_struc {
93
    std::thread thread;
94
    std::thread::id thread_ID = std::thread::id(0);
95
    std::string thread_name;
96
    int thread_socket = 0;
97
};
98
99
struct address_another_servers {
100
    int id;
101
    std::string SERVER_IP;
102
};
103
104
struct FTP_SERVER{
105
    std::string URL;
106
    std::string user;
107
    std::string pass;
108
};
109
struct iDOM_STATE{
110
    STATE houseState = STATE::UNDEFINE;
111
112
};
113
114
struct config{
115
    std::string portRS232;
116
    std::string portRS232_clock;
117
    std::string BaudRate;
118
    std::string RFLinkPort;
119
    std::string RFLinkBaudRate;
120
    int PORT;
121
    std::string SERVER_IP;
122
    std::string MPD_IP;
123
    std::string MOVIES_DB_PATH;
124
    std::string MENU_PATH;
125
    std::string THREAD_MPD   = "NULL";
126
    std::string THREAD_IRDA  = "NULL";
127
    std::string THREAD_CRON  = "NULL";
128
    std::string THREAD_RS232 = "NULL";
129
    std::string THREAD_DUMMY = "NULL";
130
    std::string TS_KEY= " gg ";
131
    std::string cameraLedON = "";
132
    std::string cameraLedOFF ="";
133
    std::string cameraURL="";
134
    std::string facebookAccessToken = "";
135
    std::string viberToken = "NULL";
136
    std::string viberAvatar;
137
    std::vector <std::string> viberReceiver;
138
    std::string viberSender;
139
    std::string radio433MHzConfigFile;
140
    std::string omxplayerFile = "NULL";
141
    int ID_server = 0;
142
    int v_delay;
143
    bool encrypted = true;
144
145
    FTP_SERVER ftpServer;
146
    std::string lightningApiURL = "NULL";
147
    std::string saveFilePath = "NULL";
148
};
149
150
struct LED_Strip{
151
    std::string from;
152
    std::string to;
153
    std::string R;
154
    std::string G;
155
    std::string B;
156
    std::string colorName;
157
158
    LED_Strip (int from, int to, int r, int g, int b, std::string colorName = "NULL"):from(std::to_string(from)),
159
        to(std::to_string(to)),
160
        R(std::to_string(r)),
161
        G(std::to_string(g)),
162
        B(std::to_string(b)),
163
        colorName(colorName)
164
    {
165
166
    }
167
    LED_Strip (const std::string& from,
168
               const std::string& to,
169
               const std::string& r,
170
               const std::string& g,
171
               const std::string& b,
172
               const std::string& colorName = "NULL"):
173
        from(from),
174
        to(to),
175
        R(r),
176
        G(g),
177
        B(b),
178
        colorName(colorName)
179
    {
180
181
    }
182
183
    void set (const std::string& from,
184
              const std::string& to,
185
              const std::string& r,
186
              const std::string& g,
187
              const std::string& b,
188
              const std::string& colorName = "NULL")
189
    {
190
        this->from =from;
191
        this->to = to;
192
        R = r;
193
        G = g;
194
        B = b;
195
        this->colorName =colorName;
196
    }
197
198
    void set (int from, int to, int r, int g, int b, std::string colorName = "NULL"){
199
        this->from = std::to_string(from);
200
        this->to = std::to_string(to);
201
        R = std::to_string(r);
202
        G = std::to_string(g);
203
        B = std::to_string(b);
204
        this->colorName =colorName;
205
    }
206
207
    std::string getColorName() const{
208
        return colorName;
209
    }
210
211
    std::string get(unsigned int _from, unsigned int _to) const{
212
        if (_from != 0 || _to != 60){
213
            return "LED:["+std::to_string(_from)+"-"+std::to_string(_to)+"-"+R+"-"+G+"-"+B+"];";
214
        }
215
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
216
    }
217
218
    std::string makeCommand(const std::string& from,
219
                            const std::string& to,
220
                            const std::string& R,
221
                            const std::string& G,
222
                            const std::string& B){
223
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
224
    }
225
};
226
227
struct pilot_led{
228
    unsigned int counter=0;
229
    std::vector<LED_Strip> colorLED   = { LED_Strip(1,60,237,145,33 ,"carrot orange"),
230
                                          LED_Strip(1,60,255,0,0    ,"red"),
231
                                          LED_Strip(1,60,0,255,0    ,"green"),
232
                                          LED_Strip(1,60,0,0,255    ,"blue"),
233
                                          LED_Strip(1,60,255,255,255,"white"),
234
                                          LED_Strip(1,60,255,255,0  ,"yellow"),
235
                                          LED_Strip(1,60,0,255,255  ,"cyan"),
236
                                          LED_Strip(1,60,255,0,255  ,"magenta")
237
                                        };
238
};
239
240
class command; // for struc thread_data req
241
class iDomTOOLS;
242
class RADIO_EQ_CONTAINER;
243
class RFLinkHandler;
244
245
struct thread_data{
246
    int s_client_sock;
247
    struct sockaddr_in from;
248
    struct config *server_settings = NULL;
249
    struct s_pointer pointer;
250
    LCD_c *mainLCD = NULL;
251
    files_tree *main_tree = NULL;
252
    menu_tree *main_MENU = NULL;
253
    iDomTOOLS *main_iDomTools = NULL;
254
    RFLinkHandler *main_RFLink = NULL;
255
    std::array<Thread_array_struc, iDomConst::MAX_CONNECTION> *main_THREAD_arr = NULL;
256
    time_t start;
257
    time_t now_time;
258
    int sleeper;
259
    std::map <std::string, std::unique_ptr <KEY> > key_map;
260
    MPD_info *ptr_MPD_info = NULL;
261
    pilot_led * ptr_pilot_led = NULL;
262
    std::map <std::string, std::unique_ptr<command> >* commandMapPtr = NULL;
263
    event_counters_handler myEventHandler;
264
    std::string encriptionKey = "40%";
265
    iDomSTATUS *main_iDomStatus;
266
    iDOM_STATE idom_all_state;
267
    ALERT alarmTime;
268
    std::shared_ptr<RADIO_EQ_CONTAINER> main_REC;
269
    iDomStateEnum iDomProgramState = iDomStateEnum::WORKING;
270
};
271
272
struct thread_data_rs232{
273
    std::string portRS232;
274
    std::string portRS232_clock;
275
    std::string BaudRate;
276
    struct s_pointer pointer;
277
};
278
279
#endif // GLOBAL_H
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/c_irda_logic/c_irda_logic.cpp
Line
Count
Source
1
#include "c_irda_logic.h"
2
#include "../iDom_server_OOP.h"
3
#include "../thread_functions/iDom_thread.h"
4
5
void c_irda_logic::irdaMPD(PILOT_KEY X)
6
10
{
7
10
    switch (X){
8
10
    case PILOT_KEY::KEY_POWER:
9
1
        mpd_queue._add(MPD_COMMAND::STOP);
10
1
        break;
11
10
    case PILOT_KEY::KEY_TV:
12
1
        mpd_queue._add(MPD_COMMAND::PLAY);
13
1
        break;
14
10
    case PILOT_KEY::KEY_VOLUMEDOWN:
15
1
        mpd_queue._add(MPD_COMMAND::VOLDOWN);
16
1
        break;
17
10
    case PILOT_KEY::KEY_VOLUMEUP:
18
1
        mpd_queue._add(MPD_COMMAND::VOLUP);
19
1
        break;
20
10
    case PILOT_KEY::KEY_AUDIO:
21
1
        mpd_queue._add(MPD_COMMAND::PAUSE);
22
1
        break;
23
10
    case PILOT_KEY::KEY_UP:
24
1
        mpd_queue._add(MPD_COMMAND::NEXT);
25
1
        break;
26
10
    case PILOT_KEY::KEY_DOWN:
27
1
        mpd_queue._add(MPD_COMMAND::PREV);
28
1
        break;
29
10
    default:
30
3
        log_file_mutex.mutex_lock();
31
3
        log_file_cout << CRITICAL << "nieznana komenda MPD z pilota "<< std::endl;
32
3
        log_file_mutex.mutex_unlock();
33
3
        break;
34
10
    }
35
10
}
36
37
void c_irda_logic::sleeperLogic(PILOT_KEY X)
38
10
{
39
10
    my_data->mainLCD->set_print_song_state(100);
40
10
    my_data->mainLCD->printString(true,0,0,std::to_string(my_data->sleeper)+" minut");
41
10
42
10
    switch (X){
43
10
    case PILOT_KEY::KEY_EXIT:
44
1
    {
45
1
        my_data->sleeper=0;
46
1
        my_data->mainLCD->set_print_song_state(0);
47
1
        who = PILOT_STATE::MPD;
48
1
        break;
49
10
    }
50
10
    case PILOT_KEY::KEY_UP:
51
4
    {
52
4
        ++my_data->sleeper;
53
4
        my_data->mainLCD->printString(true,0,0,std::to_string(my_data->sleeper)+" minut");
54
4
        break;
55
10
    }
56
10
    case PILOT_KEY::KEY_DOWN:
57
1
    {
58
1
        --my_data->sleeper;
59
1
        my_data->mainLCD->printString(true,0,0,std::to_string(my_data->sleeper)+" minut");
60
1
        break;
61
10
    }
62
10
    case PILOT_KEY::KEY_CHANNELUP:
63
1
    {
64
1
        my_data->sleeper+=10;
65
1
        my_data->mainLCD->printString(true,0,0,std::to_string(my_data->sleeper)+" minut");
66
1
        break;
67
10
    }
68
10
    case PILOT_KEY::KEY_CHANNELDOWN:
69
1
    {
70
1
        my_data->sleeper-=10;
71
1
        my_data->mainLCD->printString(true,0,0,std::to_string(my_data->sleeper)+" minut");
72
1
        break;
73
10
    }
74
10
    case PILOT_KEY::KEY_OK:
75
1
    {
76
1
        iDOM_THREAD::start_thread("Sleeper MPD",useful_F::sleeper_mpd,my_data);
77
1
        my_data->mainLCD->printString(true,1,0,"SLEEPer START");
78
1
        my_data->mainLCD->set_print_song_state(0);
79
1
        who = PILOT_STATE::MPD;
80
1
        break;
81
10
    }
82
10
    default:
83
1
        log_file_mutex.mutex_lock();
84
1
        log_file_cout << CRITICAL << "nieznany case w sleeperLogic"<< std::endl;
85
1
        log_file_mutex.mutex_unlock();
86
1
        break;
87
10
    }
88
10
}
89
90
void c_irda_logic::projectorLogic(PILOT_KEY X)
91
12
{
92
12
    my_data->mainLCD->set_print_song_state(100);
93
12
    my_data->mainLCD->printString(false,2,1,"  PROJEKTOR   ");
94
12
95
12
    switch (X)
96
12
    {
97
12
    case PILOT_KEY::KEY_EXIT:
98
2
    {
99
2
        my_data->mainLCD->set_print_song_state(0);
100
2
        who = PILOT_STATE::MPD;
101
2
102
2
        if(my_data->ptr_MPD_info->isPlay == true){
103
1
            iDomTOOLS::MPD_play(my_data);
104
1
        }
105
1
        else {
106
1
            iDomTOOLS::turnOffSpeakers();
107
1
            my_data->mainLCD->set_print_song_state(0); // off display
108
1
            my_data->mainLCD->set_lcd_STATE(0);
109
1
        }
110
2
        break;
111
12
    }
112
12
    case PILOT_KEY::DUMMY:
113
1
    {
114
1
        break;
115
12
    }
116
12
    case PILOT_KEY::KEY_VOLUMEUP:
117
1
    {
118
1
        useful_F_libs::write_to_mkfifo(my_data->server_settings->omxplayerFile, "+");
119
1
        break;
120
12
    }
121
12
    case PILOT_KEY::KEY_VOLUMEDOWN:
122
1
    {
123
1
        useful_F_libs::write_to_mkfifo(my_data->server_settings->omxplayerFile, "-");
124
1
        break;
125
12
    }
126
12
    case PILOT_KEY::KEY_OK:
127
1
    {
128
1
        my_data->mainLCD->set_print_song_state(1000);
129
1
        my_data->mainLCD->printString(false,0,0,"ODTWARZAM VIDEO");
130
1
        useful_F_libs::write_to_mkfifo(my_data->server_settings->omxplayerFile, "p");
131
1
        break;
132
12
    }
133
12
    case PILOT_KEY::KEY_POWER:
134
1
    {
135
1
        //system("echo -n q > /mnt/ramdisk/cmd &"); // zamykanie omxplayera
136
1
        useful_F_libs::write_to_mkfifo(my_data->server_settings->omxplayerFile, "q");
137
1
        break;
138
12
    }
139
12
    case PILOT_KEY::KEY_DOWN:
140
1
    {
141
1
        useful_F::runLinuxCommand("echo -n $'\x1b\x5b\x43' > /mnt/ramdisk/cmd"); // do przodu
142
1
        //write_to_mkfifo("$'\x1b\x5b\x43'");
143
1
        break;
144
12
    }
145
12
    case PILOT_KEY::KEY_UP:
146
1
    {
147
1
        useful_F::runLinuxCommand("echo -n $'\x1b\x5b\x44' > /mnt/ramdisk/cmd"); // do tylu
148
1
        // write_to_mkfifo("$'\x1b\x5b\x44'");
149
1
        break;
150
12
    }
151
12
    case PILOT_KEY::KEY_CHANNELUP:
152
1
    {
153
1
        //system("echo -n o > /mnt/ramdisk/cmd"); // do przodu
154
1
        useful_F_libs::write_to_mkfifo(my_data->server_settings->omxplayerFile, "o");
155
1
        break;
156
12
    }
157
12
    case PILOT_KEY::KEY_CHANNELDOWN:
158
1
    {
159
1
        //system("echo -n i > /mnt/ramdisk/cmd"); // do tylu
160
1
        useful_F_libs::write_to_mkfifo(my_data->server_settings->omxplayerFile, "i");
161
1
        break;
162
12
    }
163
12
    default:
164
1
        log_file_mutex.mutex_lock();
165
1
        log_file_cout << CRITICAL << "nieznany case w projector"<< std::endl;
166
1
        log_file_mutex.mutex_unlock();
167
1
        break;
168
12
    }
169
12
}
170
171
void c_irda_logic::movieLogic(PILOT_KEY X)
172
14
{
173
14
    switch (X)
174
14
    {
175
14
    case PILOT_KEY::KEY_EXIT:
176
1
    {
177
1
        my_data->mainLCD->set_print_song_state(0);
178
1
        my_data->mainLCD->set_lcd_STATE(2);
179
1
        who = PILOT_STATE::MPD; // koniec przegladania katalogow
180
1
        break;
181
14
    }
182
14
    case PILOT_KEY::KEY_VOLUMEUP:
183
3
    {
184
3
        my_data->main_tree->next(); // naspteny katalog
185
3
        break;
186
14
    }
187
14
    case PILOT_KEY::KEY_VOLUMEDOWN:
188
5
    {
189
5
        my_data->main_tree->previous(); //poprzedni katalog
190
5
        break;
191
14
    }
192
14
    case PILOT_KEY::KEY_OK:
193
3
    {
194
3
        // whodze w katalog lub odtwarzma plik
195
3
196
3
        if (my_data->main_tree->is_file() == false)
197
1
        {
198
1
            my_data->main_tree->enter_dir();
199
1
            my_data->main_tree->show_list();
200
1
        }
201
2
        else
202
2
        {
203
2
            std::cout << " URUCHAMIAM PLIK! " <<my_data->main_tree->show_list() <<std::endl;
204
2
205
2
            std::string command = "/home/pi/programowanie/iDom_server_OOP/script/PYTHON/iDom_movie.py ";
206
2
            command+=my_data->main_tree->show_list();
207
2
            useful_F::runLinuxCommand(command);
208
2
            std::cout << " WYSTARTOWALEM!!";
209
2
            my_data->mainLCD->set_lcd_STATE(-1);
210
2
            my_data->mainLCD->printString(true,0,0,"odtwarzam film");
211
2
            my_data->mainLCD->printString(false,0,1,my_data->main_tree->show_list());
212
2
            who = PILOT_STATE::PROJECTOR;
213
2
214
2
            log_file_mutex.mutex_lock();
215
2
            log_file_cout << INFO << "odtwarzam film "<< my_data->ptr_MPD_info->isPlay << std::endl;
216
2
            log_file_mutex.mutex_unlock();
217
2
218
2
            if (my_data->ptr_MPD_info->isPlay == true){
219
1
                iDomTOOLS::MPD_pause(); // projektor wlaczony wiec pauzuje radio
220
1
            }
221
1
            else{
222
1
                iDomTOOLS::turnOnSpeakers();
223
1
                puts("wlaczam glosnik do filmu");
224
1
            }
225
2
        }
226
3
        break;
227
14
    }
228
14
    case PILOT_KEY::KEY_UP:
229
1
    {
230
1
        my_data->main_tree->back_dir();
231
1
        break;
232
14
    }
233
14
    default:
234
1
        log_file_mutex.mutex_lock();
235
1
        log_file_cout << CRITICAL << "nieznany case w moveLogic"<< std::endl;
236
1
        log_file_mutex.mutex_unlock();
237
1
        break;
238
14
    }
239
14
240
14
    my_data->main_tree->show_list();
241
14
}
242
243
void c_irda_logic::menuLogic(PILOT_KEY X)
244
39
{
245
39
    switch (X)
246
39
    {
247
39
    case PILOT_KEY::KEY_EXIT:
248
1
    {
249
1
        my_data->mainLCD->set_print_song_state(0);
250
1
        my_data->mainLCD->set_lcd_STATE(2);
251
1
        who = PILOT_STATE::MPD; // koniec przegladania katalogow
252
1
        break;
253
39
    }
254
39
    case PILOT_KEY::KEY_VOLUMEUP:
255
23
    {
256
23
        my_data->main_MENU->next(); // naspteny katalog
257
23
        break;
258
39
    }
259
39
    case PILOT_KEY::KEY_VOLUMEDOWN:
260
6
    {
261
6
        my_data->main_MENU->previous(); //poprzedni katalog
262
6
        break;
263
39
    }
264
39
    case PILOT_KEY::KEY_OK:
265
7
    {
266
7
        // whodze w katalog lub odtwarzma plik
267
7
268
7
        if (my_data->main_MENU->is_file() == false)
269
1
        {
270
1
            my_data->main_MENU->enter_dir();
271
1
            my_data->main_MENU->show_list();
272
1
        }
273
6
        else
274
6
        {
275
6
            // menu start
276
6
            if (my_data->main_MENU->show_list() == "5.SLEEPer"){
277
2
                std::cout << " POBUDKA!!!!" << std::endl;
278
2
                who=PILOT_STATE::SLEEPER;
279
2
            }
280
4
            else if (my_data->main_MENU->show_list() == "2.TEMPERATURA"){
281
1
                std::cout << " temperatura !!!!" << std::endl;
282
1
                who=PILOT_STATE::MPD;
283
1
                _add(PILOT_KEY::KEY_SAT);
284
1
            }
285
3
            else if (my_data->main_MENU->show_list() == "4.PLIKI"){
286
3
                std::cout << " do filmow" << std::endl;
287
3
                who=PILOT_STATE::MPD;
288
3
                _add(PILOT_KEY::KEY_EPG);
289
3
                _add(PILOT_KEY::KEY_VOLUMEUP);
290
3
            }
291
6
        }
292
7
        break;
293
39
    }
294
39
    case PILOT_KEY::KEY_UP:
295
1
    {
296
1
        my_data->main_MENU->back_dir();
297
1
        break;
298
39
    }
299
39
    default:
300
1
        log_file_mutex.mutex_lock();
301
1
        log_file_cout << CRITICAL << "nieznany case w menuLogic"<< std::endl;
302
1
        log_file_mutex.mutex_unlock();
303
1
        break;
304
39
305
39
    }
306
39
    my_data->main_MENU->show_list();
307
39
}
308
309
void c_irda_logic::mainPilotHandler(PILOT_KEY X)
310
36
{
311
36
    switch (X){
312
36
313
36
    case PILOT_KEY::KEY_RADIO:
314
1
    {
315
1
        who = PILOT_STATE::PROJECTOR;
316
1
        _add(PILOT_KEY::DUMMY);
317
1
        break;
318
36
    }
319
36
320
36
    case PILOT_KEY::KEY_SUBTITLE:
321
1
    {
322
1
        my_data->mainLCD->set_lcd_STATE(10);
323
1
        my_data->mainLCD->printString(true,0,0,"GASZE LEDy");
324
1
        std::string temp_str="";
325
1
        temp_str.erase();
326
1
        temp_str += my_data->main_iDomTools->ledOFF();
327
1
        my_data->mainLCD->printString(false,0,1,temp_str);
328
1
        who=PILOT_STATE::MPD;
329
1
        break;
330
36
    }
331
36
332
36
    case PILOT_KEY::KEY_LANGUAGE:
333
9
    {
334
9
        my_data->mainLCD->set_lcd_STATE(10);
335
9
        my_data->mainLCD->printString(true,0,0,"ZAPALAM LEDy");
336
9
        std::string temp_str = my_data->ptr_pilot_led->colorLED[my_data->ptr_pilot_led->counter].getColorName();
337
9
        my_data->main_iDomTools->ledOn(my_data->ptr_pilot_led->colorLED[my_data->ptr_pilot_led->counter]);
338
9
339
9
        if (++my_data->ptr_pilot_led->counter > my_data->ptr_pilot_led->colorLED.size()-1 )
340
1
        {
341
1
            my_data->ptr_pilot_led->counter=0;
342
1
        }
343
9
344
9
        my_data->mainLCD->printString(false,0,1,temp_str);
345
9
        who = PILOT_STATE::MPD;
346
9
        break;
347
36
    }
348
36
349
36
    case PILOT_KEY::KEY_SAT:
350
1
    {
351
1
        my_data->mainLCD->set_lcd_STATE(10);
352
1
        my_data->mainLCD->printString(true,0,0,"SMOG: "+my_data->main_iDomTools->getSmog()+" mg/m^3");
353
1
        std::string temp_str = "I:";
354
1
        std::vector<std::string> temper = my_data->main_iDomTools->getTemperature();
355
1
        //temp_str += my_data_logic->main_iDomTools->getTemperatureString();// send_to_arduino(my_data_logic,"temperature:2;");
356
1
        temp_str += temper.at(0);
357
1
        temp_str += " O:"+ temper.at(1);
358
1
        my_data->mainLCD->printString(false,0,1,temp_str+" c");
359
1
        who = PILOT_STATE::MPD;
360
1
        break;
361
36
    }
362
36
363
36
    case PILOT_KEY::KEY_EPG:
364
3
        who = PILOT_STATE::MOVIE;
365
3
        my_data->main_tree->show_list(); //printuje pierwszy element
366
3
        my_data->mainLCD->set_print_song_state(100);
367
3
        break;
368
36
369
36
    case PILOT_KEY::KEY_MENU:
370
7
        who = PILOT_STATE::MENU;
371
7
        my_data->main_MENU->show_list();
372
7
        my_data->mainLCD->set_print_song_state(100);
373
7
        break;
374
36
    case PILOT_KEY::KEY_FAVORITES:
375
1
        my_data->main_iDomTools->turnOnOffPrinter();
376
1
        break;
377
36
    case PILOT_KEY::KEY_TEXT:
378
2
        my_data->main_iDomTools->turnOnOff433MHzSwitch("listwa");
379
2
        break;
380
36
    case PILOT_KEY::KEY_REFRESH:
381
1
        my_data->main_iDomTools->startKodi_Thread();
382
1
        break;
383
36
    default:
384
10
        irdaMPD(X);
385
36
    }
386
36
}
387
388
c_irda_logic::c_irda_logic(thread_data *my_data):my_data(my_data)
389
12
{
390
12
    // my_data = my_data;
391
12
    who = PILOT_STATE::MPD;
392
12
}
393
394
void c_irda_logic::_add(PILOT_KEY X)
395
111
{
396
111
    switch (who){
397
111
    case PILOT_STATE::MPD:
398
35
        mainPilotHandler(X);
399
35
        break;
400
111
    case PILOT_STATE::SLEEPER:
401
10
        sleeperLogic(X);
402
10
        break;
403
111
    case PILOT_STATE::PROJECTOR:
404
12
        projectorLogic(X);
405
12
        break;
406
111
    case PILOT_STATE::MOVIE:
407
14
        movieLogic(X);
408
14
        break;
409
111
    case PILOT_STATE::MENU:
410
39
        menuLogic(X);
411
39
        break;
412
111
    default:
413
1
        log_file_mutex.mutex_lock();
414
1
        log_file_cout << CRITICAL << "nieznany pilotState"<< std::endl;
415
1
        log_file_mutex.mutex_unlock();
416
1
        break;
417
111
    }
418
111
}
419
420
//PILOT_KEY c_irda_logic::_get( )
421
//{
422
//    PILOT_KEY temp = PILOT_KEY::DUMMY;
423
//    if (irda_queue.empty() == false){
424
//        temp = irda_queue.front();
425
//        irda_queue.pop();
426
//    }
427
//    return temp;
428
//}
429
430
//int c_irda_logic::_size() const
431
//{
432
//    return irda_queue.size();
433
//}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/c_connection/c_connection.cpp
Line
Count
Source (jump to first uncovered line)
1
#include <iostream>
2
#include "c_connection.h"
3
4
C_connection::C_connection (thread_data *my_data):c_socket(my_data->s_client_sock),
5
    c_from(my_data->from),recv_size(0)
6
8
{
7
8
    this -> pointer = &my_data->pointer;
8
8
    this -> my_data = my_data;
9
8
    this->m_encrypted = my_data->server_settings->encrypted;
10
8
    std::fill(std::begin(c_buffer),std::end(c_buffer),',');
11
8
    onStartConnection();
12
8
}
13
14
C_connection::~C_connection()
15
8
{
16
8
    if( mainCommandHandler != std::nullptr_t())
17
8
    {
18
3
        my_data->mainLCD->set_print_song_state(0);
19
3
        my_data->mainLCD->set_lcd_STATE(2);
20
3
        delete mainCommandHandler;
21
3
    }
22
8
    my_data->mainLCD->set_print_song_state(0);
23
8
    my_data->mainLCD->set_lcd_STATE(2);
24
8
25
8
    useful_F::sleep(3);
26
8
27
8
    shutdown(c_socket, SHUT_RDWR );
28
8
    useful_F::clearThreadArray(my_data);
29
8
    puts("C_connection::~C_connection()");
30
8
}
31
32
int C_connection::c_send(int para)
33
1
{
34
1
    crypto(str_buf,m_encriptionKey,m_encrypted); //BUG - naprawic czytanie flagi z parametru klasy
35
1
    std::string len = std::to_string( str_buf.size());
36
1
    crypto(len,m_encriptionKey,m_encrypted);
37
1
    if(( send( c_socket, len.c_str() ,len.length(), para ) ) <= 0 )
38
1
    {
39
1
        return -1;
40
1
    }
41
1
    recv_size = recv( c_socket, c_buffer , MAX_buf, para );
42
0
43
0
    if(recv_size < 0 )
44
0
    {
45
0
        log_file_mutex.mutex_lock();
46
0
        log_file_cout << ERROR << "C_connection::c_send(int para) recv() error - " << strerror( errno ) << std::endl;
47
0
        log_file_mutex.mutex_unlock();
48
0
        return -1;
49
0
    }
50
0
    else if (recv_size == 0)
51
0
    {
52
0
        return -1;
53
0
    }
54
0
55
0
    auto len_send = str_buf.length();
56
0
57
0
    while (len_send > 0)
58
0
    {
59
0
        auto len_temp = send( c_socket, str_buf.c_str() ,str_buf.length(), para );
60
0
        if(len_temp <= 0 )
61
0
        {
62
0
            return -1;
63
0
        }
64
0
        len_send -= len_temp;
65
0
        str_buf.erase(0,len_temp);
66
0
    }
67
0
    return 0;
68
0
}
69
70
int C_connection::c_send(const std::string &command )
71
1
{
72
1
    str_buf = command;
73
1
    return c_send(0);
74
1
}
75
76
int C_connection::c_recv(int para)
77
1
{
78
1
    struct timeval tv;
79
1
    tv.tv_sec = 90;
80
1
    tv.tv_usec = 0;
81
1
    setsockopt(c_socket,SOL_SOCKET,SO_RCVTIMEO,(char*)&tv , sizeof(struct timeval));
82
1
83
1
    recv_size = recv(c_socket, c_buffer, MAX_buf, para);
84
1
85
1
    if(recv_size < 0)
86
1
    {
87
1
        log_file_mutex.mutex_lock();
88
1
        log_file_cout << ERROR << "C_connection::c_recv(int para) recv() error - " << strerror( errno ) << std::endl;
89
1
        log_file_mutex.mutex_unlock();
90
1
        return -1;
91
1
    }
92
1
    else if (recv_size == 0)
93
0
    {
94
0
        return -1;
95
0
    }
96
1
    return recv_size;
97
1
}
98
99
void C_connection::c_analyse(int recvSize)
100
3
{
101
3
    std::string buf;
102
3
103
3
    buf = c_read_buf(recvSize);
104
3
    my_data->myEventHandler.run("command")->addEvent(buf);
105
3
    std::vector <std::string> command;
106
3
    try{
107
3
    useful_F::tokenizer(command," \n,", buf);
108
3
    }
109
3
    catch (std::string& k){
110
1
        log_file_mutex.mutex_lock();
111
1
        log_file_cout << DEBUG << "brak komendy - " << k << std::endl;
112
1
        log_file_mutex.mutex_unlock();
113
1
        str_buf = "empty command";
114
1
        return;
115
1
    }
116
3
117
3
#ifdef BT_TEST
118
3
    std::cout << "komenda: " << str_buf << " command.size() " << command.size() << std::endl;
119
2
#endif
120
2
    str_buf = "unknown command\n";
121
2
122
2
    for(std::string t : command)
123
5
    {
124
5
        str_buf += t+" ";
125
5
    }
126
2
127
2
    str_buf = mainCommandHandler->run(command,my_data);
128
2
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/c_irda_logic/test/c_irda_logic_BT.cpp
Line
Count
Source (jump to first uncovered line)
1
#include <gtest/gtest.h>
2
#include "../../iDom_server_OOP.h"
3
#include "test_data.h"
4
#include "../../../iDom_server_OOP/src/iDomTools/test/iDomTools_fixture.h"
5
#include "../c_irda_logic.h"
6
7
8
class c_irda_logic_fixture : public iDomTOOLS_ClassTest
9
{
10
public:
11
    std::unique_ptr<c_irda_logic> test_irda;
12
    menu_tree* test_menuTree;
13
    files_tree* test_filesTree;
14
    std::string test_omxplayerFile = "../config/cmd_test";
15
    void SetUp()
16
12
    {
17
12
        iDomTOOLS_ClassTest::SetUp();
18
12
        test_irda = std::make_unique<c_irda_logic>(&test_my_data);
19
12
        test_menuTree = new menu_tree("../config/MENU/", test_my_data.mainLCD);
20
12
        test_my_data.main_MENU = test_menuTree;
21
12
22
12
        test_filesTree = new files_tree("../config/MOVIE/", test_my_data.mainLCD);
23
12
        test_my_data.main_tree = test_filesTree;
24
12
25
12
        test_my_data.server_settings->omxplayerFile =  test_omxplayerFile;
26
12
27
12
        std::cout << "c_irda_logic_fixture SetUp()"<<std::endl;
28
12
    }
29
30
    void TearDown()
31
12
    {
32
12
        delete test_menuTree;
33
12
        delete test_filesTree;
34
12
        iDomTOOLS_ClassTest::TearDown();
35
12
        std::cout << "c_irda_logic_fixture TearDown()"<<std::endl;
36
12
    }
37
};
38
39
TEST_F(c_irda_logic_fixture, kodi)
40
1
{
41
1
    std::array<Thread_array_struc,iDomConst::MAX_CONNECTION >test_ThreadArrayStruc;
42
1
43
11
    for (int i = 0 ; i < iDomConst::MAX_CONNECTION; i++)
44
10
        test_ThreadArrayStruc.at(i).thread_socket = i+1;
45
1
    test_ThreadArrayStruc.at(3).thread_socket = 0;
46
1
    test_my_data.main_THREAD_arr = &test_ThreadArrayStruc;
47
1
48
1
    test_my_data.main_iDomTools->unlockHome();
49
1
    test_my_data.main_iDomStatus->setObjectState("music",STATE::PAUSE);
50
1
    test_my_data.main_iDomStatus->setObjectState("speakers",STATE::OFF);
51
1
    test_irda->_add(PILOT_KEY::KEY_REFRESH);
52
1
    sleep(1);
53
1
}
54
55
TEST_F(c_irda_logic_fixture, turnOnOffListwa)
56
1
{
57
1
    test_my_data.main_iDomTools->unlockHome();
58
1
    test_my_data.main_iDomStatus->setObjectState("listwa",STATE::OFF);
59
1
60
1
    EXPECT_EQ(test_my_data.main_REC->getEqPointer("listwa")->getState(), STATE::UNDEFINE);
61
1
    test_irda->_add(PILOT_KEY::KEY_TEXT);
62
1
63
2
    EXPECT_EQ(test_my_data.main_REC->getEqPointer("listwa")->getState(),
64
2
              STATE::ON) << "wrong state: "
65
2
                         << stateToString(test_my_data.main_REC->getEqPointer("listwa")->getState());
66
1
    test_irda->_add(PILOT_KEY::KEY_TEXT);
67
1
68
2
    EXPECT_EQ(test_my_data.main_REC->getEqPointer("listwa")->getState(),
69
2
              STATE::OFF) << "wrong state: "
70
2
                          << stateToString(test_my_data.main_REC->getEqPointer("listwa")->getState());
71
1
}
72
73
TEST_F(c_irda_logic_fixture, turnOnOffPrinter)
74
1
{
75
1
    setReturnPinState(0);
76
1
    test_my_data.main_iDomTools->unlockHome();
77
1
    test_my_data.main_iDomStatus->setObjectState("printer", STATE::OFF);
78
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("printer"),
79
1
              STATE::OFF);
80
1
81
1
    test_irda->mainPilotHandler(PILOT_KEY::KEY_FAVORITES);
82
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("printer"),
83
1
              STATE::ON);
84
1
    std::cout <<"event: " << test_my_data.myEventHandler.run("230V")->getEvent() <<std::endl;
85
1
}
86
87
TEST_F(c_irda_logic_fixture, irdaMPD)
88
1
{
89
1
    blockQueue test_Q;
90
1
    test_Q._clearAll();
91
1
92
1
    test_irda->_add(PILOT_KEY::KEY_POWER);
93
1
    EXPECT_EQ(test_Q._get(), MPD_COMMAND::STOP);
94
1
95
1
    test_irda->_add(PILOT_KEY::KEY_TV);
96
1
    EXPECT_EQ(test_Q._get(), MPD_COMMAND::PLAY);
97
1
98
1
    test_irda->_add(PILOT_KEY::KEY_VOLUMEDOWN);
99
1
    EXPECT_EQ(test_Q._get(), MPD_COMMAND::VOLDOWN);
100
1
101
1
    test_irda->_add(PILOT_KEY::KEY_VOLUMEUP);
102
1
    EXPECT_EQ(test_Q._get(), MPD_COMMAND::VOLUP);
103
1
104
1
    test_irda->_add(PILOT_KEY::KEY_AUDIO);
105
1
    EXPECT_EQ(test_Q._get(), MPD_COMMAND::PAUSE);
106
1
107
1
    test_irda->_add(PILOT_KEY::KEY_UP);
108
1
    EXPECT_EQ(test_Q._get(), MPD_COMMAND::NEXT);
109
1
110
1
    test_irda->_add(PILOT_KEY::KEY_DOWN);
111
1
    EXPECT_EQ(test_Q._get(), MPD_COMMAND::PREV);
112
1
113
1
    test_irda->_add(PILOT_KEY::KEY_2); //default
114
1
    EXPECT_EQ(test_Q._size(), 0);
115
1
}
116
TEST_F(c_irda_logic_fixture, sleeper_Logic_EXIT)
117
1
{
118
1
    test_my_data.sleeper = 0;
119
1
    EXPECT_EQ(test_my_data.sleeper, 0);
120
1
    test_irda->_add(PILOT_KEY::KEY_MENU);
121
4
    do {
122
4
        test_irda->_add(PILOT_KEY::KEY_VOLUMEUP);
123
4
    } while(TEST_DATA::LCD_print != "5.SLEEPer");
124
5
    do {
125
5
        test_irda->_add(PILOT_KEY::KEY_VOLUMEDOWN);
126
5
    } while(TEST_DATA::LCD_print != "5.SLEEPer");
127
1
    test_irda->_add(PILOT_KEY::KEY_OK);
128
1
    test_irda->_add(PILOT_KEY::KEY_UP);
129
1
    EXPECT_EQ(test_my_data.sleeper, 1);
130
1
    test_irda->_add(PILOT_KEY::KEY_UP);
131
1
    EXPECT_EQ(test_my_data.sleeper, 2);
132
1
    test_irda->_add(PILOT_KEY::KEY_EXIT);
133
1
    EXPECT_EQ(test_my_data.sleeper, 0);
134
1
}
135
136
TEST_F(c_irda_logic_fixture, sleeper_Logic_OK)
137
1
{
138
1
    std::cout << test_my_data.main_REC->listAllName() << std::endl;
139
1
140
1
    std::array<Thread_array_struc,iDomConst::MAX_CONNECTION> test_ThreadArrayStruc;
141
1
142
11
    for (int i = 0 ; i < iDomConst::MAX_CONNECTION; i++)
143
10
        test_ThreadArrayStruc.at(i).thread_socket = i+1;
144
1
    test_ThreadArrayStruc.at(3).thread_socket = 0;
145
1
    test_my_data.main_THREAD_arr = &test_ThreadArrayStruc;
146
1
    test_my_data.sleeper = 0;
147
1
    EXPECT_EQ(test_my_data.sleeper, 0);
148
1
    test_irda->_add(PILOT_KEY::KEY_MENU);
149
4
    do {
150
4
        test_irda->_add(PILOT_KEY::KEY_VOLUMEUP);
151
4
    } while(TEST_DATA::LCD_print != "5.SLEEPer");
152
1
    test_irda->_add(PILOT_KEY::KEY_OK);
153
1
    test_irda->_add(PILOT_KEY::KEY_UP);
154
1
    EXPECT_EQ(test_my_data.sleeper, 1);
155
1
    test_irda->_add(PILOT_KEY::KEY_UP);
156
1
    EXPECT_EQ(test_my_data.sleeper, 2);
157
1
    test_irda->_add(PILOT_KEY::KEY_CHANNELUP);
158
1
    EXPECT_EQ(test_my_data.sleeper, 12);
159
1
    test_irda->_add(PILOT_KEY::KEY_CHANNELDOWN);
160
1
    EXPECT_EQ(test_my_data.sleeper, 2);
161
1
    test_irda->_add(PILOT_KEY::KEY_DOWN);
162
1
    EXPECT_EQ(test_my_data.sleeper, 1);
163
1
    test_irda->_add(PILOT_KEY::KEY_OK);
164
1
    sleep(2);
165
1
    EXPECT_EQ(test_my_data.sleeper, 0);
166
1
    test_irda->_add(PILOT_KEY::KEY_EXIT);
167
1
    EXPECT_EQ(test_my_data.sleeper, 0);\
168
1
169
1
    //////////////default
170
1
    test_irda->who = PILOT_STATE::SLEEPER;
171
1
    test_irda->_add(PILOT_KEY::KEY_0); //default
172
1
}
173
174
TEST_F(c_irda_logic_fixture, LED_ON_OFF)
175
1
{
176
1
    EXPECT_EQ( test_my_data.myEventHandler.run("LED")->getLast1minNumberEvent(),0);
177
10
    for (int i = 1 ; i < test_my_data.ptr_pilot_led->colorLED.size()+2; ++i)
178
9
    {
179
9
        test_irda->_add(PILOT_KEY::KEY_LANGUAGE);
180
9
        EXPECT_EQ( test_my_data.myEventHandler.run("LED")->getLast1minNumberEvent(),i);
181
9
        EXPECT_THAT(test_my_data.myEventHandler.run("LED")->getEvent(),
182
9
                    testing::HasSubstr("LED can not start due to home state: UNDEFINE"));
183
9
    }
184
1
    test_irda->_add(PILOT_KEY::KEY_SUBTITLE);
185
1
}
186
TEST_F(c_irda_logic_fixture, temp_smogINFO)
187
1
{
188
1
    TEST_DATA::return_httpPost = "ok.\n";
189
1
    TEST_DATA::return_send_to_arduino = "12:12";
190
1
    test_irda->_add(PILOT_KEY::KEY_MENU);
191
1
    do {
192
1
        test_irda->_add(PILOT_KEY::KEY_VOLUMEUP);
193
1
    } while(TEST_DATA::LCD_print != "2.TEMPERATURA");
194
1
195
1
    test_irda->_add(PILOT_KEY::KEY_VOLUMEUP);
196
1
    test_irda->_add(PILOT_KEY::KEY_VOLUMEDOWN);
197
1
    test_irda->_add(PILOT_KEY::KEY_OK);
198
1
    EXPECT_THAT(TEST_DATA::LCD_print, testing::HasSubstr("TEMPERATURA"));
199
1
}
200
201
TEST_F(c_irda_logic_fixture, menu_enter_dir)
202
1
{
203
1
    test_irda->_add(PILOT_KEY::KEY_MENU);
204
1
    test_irda->_add(PILOT_KEY::KEY_OK);
205
1
206
1
    EXPECT_EQ(test_irda->who, PILOT_STATE::MENU);
207
1
    test_irda->_add(PILOT_KEY::KEY_UP);
208
1
    test_irda->_add(PILOT_KEY::KEY_0); //default
209
1
    test_irda->_add(PILOT_KEY::KEY_EXIT);
210
1
    EXPECT_EQ(test_irda->who, PILOT_STATE::MPD);
211
1
}
212
TEST_F(c_irda_logic_fixture, menu_files)
213
1
{
214
1
    blockQueue  test_q;
215
1
    test_q._clearAll();
216
1
    test_my_data.idom_all_state.houseState = STATE::UNLOCK;
217
1
    int timeout = 10;
218
1
    test_irda->_add(PILOT_KEY::KEY_MENU);
219
3
    do {
220
3
        if (--timeout == 0)
221
3
            FAIL()<<"cannot find";
222
3
        test_irda->_add(PILOT_KEY::KEY_VOLUMEUP);
223
3
    } while(TEST_DATA::LCD_print != "4.PLIKI");
224
1
    test_irda->_add(PILOT_KEY::KEY_OK);
225
1
    EXPECT_EQ(test_irda->who, PILOT_STATE::MOVIE);
226
1
    timeout = 10;
227
2
    do {
228
2
        if (--timeout == 0)
229
2
            FAIL()<<"cannot find";
230
2
        test_irda->_add(PILOT_KEY::KEY_VOLUMEDOWN);
231
2
    } while(TEST_DATA::LCD_print != "GAME_OF_THRONES/");
232
1
    test_irda->_add(PILOT_KEY::KEY_OK);
233
1
    test_irda->_add(PILOT_KEY::KEY_UP);
234
1
    EXPECT_STREQ(TEST_DATA::LCD_print.c_str(),"GAME_OF_THRONES/");
235
1
    test_irda->_add(PILOT_KEY::KEY_EXIT);
236
1
    EXPECT_EQ(test_irda->who, PILOT_STATE::MPD);
237
1
    ///////////////// play - no MPD
238
1
239
1
    test_my_data.ptr_MPD_info->isPlay  = false;
240
1
    test_irda->_add(PILOT_KEY::KEY_MENU);
241
1
    timeout = 10;
242
5
    do {
243
5
        if (--timeout == 0)
244
5
            FAIL()<<"cannot find";
245
5
        test_irda->_add(PILOT_KEY::KEY_VOLUMEUP);
246
5
    } while(TEST_DATA::LCD_print != "4.PLIKI");
247
1
    test_irda->_add(PILOT_KEY::KEY_OK);
248
1
    EXPECT_EQ(test_irda->who, PILOT_STATE::MOVIE);
249
1
    timeout = 10;
250
2
    do {
251
2
        if (--timeout == 0)
252
0
            break;
253
2
        test_irda->_add(PILOT_KEY::KEY_VOLUMEDOWN);
254
2
    } while(TEST_DATA::LCD_print != "s01e02");
255
1
    test_irda->_add(PILOT_KEY::KEY_0); //default
256
1
    test_irda->_add(PILOT_KEY::KEY_OK);
257
1
    EXPECT_EQ(test_irda->who, PILOT_STATE::PROJECTOR);
258
1
    test_irda->_add(PILOT_KEY::KEY_EXIT);
259
1
    EXPECT_EQ(test_irda->who, PILOT_STATE::MPD);
260
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("speakers"),STATE::OFF);
261
1
    ///////////////// play -  MPD
262
1
    test_my_data.ptr_MPD_info->isPlay  = true;
263
1
    EXPECT_TRUE(test_my_data.ptr_MPD_info->isPlay);
264
1
    test_irda->_add(PILOT_KEY::KEY_MENU);
265
1
    timeout = 10;
266
5
    do {
267
5
        if (--timeout == 0)
268
5
            FAIL()<<"cannot find";
269
5
        test_irda->_add(PILOT_KEY::KEY_VOLUMEUP);
270
5
    } while(TEST_DATA::LCD_print != "4.PLIKI");
271
1
    test_irda->_add(PILOT_KEY::KEY_OK);
272
1
    EXPECT_EQ(test_irda->who, PILOT_STATE::MOVIE);
273
1
    timeout = 10;
274
1
    do {
275
1
        if (--timeout == 0)
276
1
            FAIL()<<"cannot find";
277
1
        test_irda->_add(PILOT_KEY::KEY_VOLUMEDOWN);
278
1
    } while(TEST_DATA::LCD_print != "s01e02");
279
1
    test_irda->_add(PILOT_KEY::KEY_OK);
280
1
    EXPECT_EQ(test_irda->who, PILOT_STATE::PROJECTOR);
281
1
282
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::PAUSE);
283
1
}
284
285
TEST_F(c_irda_logic_fixture, dummy_KEY_RADIO_and_add )
286
1
{
287
1
    test_irda->_add(PILOT_KEY::KEY_RADIO);
288
1
    EXPECT_EQ(test_irda->who, PILOT_STATE::PROJECTOR);
289
1
290
1
    test_irda->who = PILOT_STATE::LED; //not set
291
1
    test_irda->_add(PILOT_KEY::KEY_RADIO);
292
1
}
293
294
TEST_F(c_irda_logic_fixture, projektor)
295
1
{
296
1
    std::string retString;
297
1
    test_irda->who = PILOT_STATE::PROJECTOR;
298
1
    test_irda->_add(PILOT_KEY::KEY_VOLUMEUP);
299
1
    retString = useful_F_libs::read_from_mkfifo(test_omxplayerFile.c_str());
300
1
    std::cout << "DUPA: " << retString.size() << std::endl;
301
1
   // EXPECT_EQ(retString,"+");
302
1
303
1
    test_irda->_add(PILOT_KEY::KEY_VOLUMEDOWN);
304
1
    retString = useful_F_libs::read_from_mkfifo(test_omxplayerFile.c_str());
305
1
    std::cout << "DUPA: " << retString.size() << std::endl;
306
1
   // EXPECT_EQ(retString,"+");
307
1
308
1
    test_irda->_add(PILOT_KEY::KEY_OK);
309
1
    retString = useful_F_libs::read_from_mkfifo(test_omxplayerFile.c_str());
310
1
    std::cout << "DUPA: " << retString.size() << std::endl;
311
1
   // EXPECT_EQ(retString,"-");
312
1
313
1
    test_irda->_add(PILOT_KEY::KEY_POWER);
314
1
    retString = useful_F_libs::read_from_mkfifo(test_omxplayerFile.c_str());
315
1
    std::cout << "DUPA: " << retString.size() << std::endl;
316
1
   // EXPECT_EQ(retString,"q");
317
1
318
1
    test_irda->_add(PILOT_KEY::KEY_DOWN);
319
1
    retString = useful_F_libs::read_from_mkfifo(test_omxplayerFile.c_str());
320
1
    std::cout << "DUPA: " << retString.size() << std::endl;
321
1
   // EXPECT_EQ(retString,"+");
322
1
323
1
    test_irda->_add(PILOT_KEY::KEY_UP);
324
1
    retString = useful_F_libs::read_from_mkfifo(test_omxplayerFile.c_str());
325
1
    std::cout << "DUPA: " << retString.size() << std::endl;
326
1
   // EXPECT_EQ(retString,"+");
327
1
328
1
    test_irda->_add(PILOT_KEY::KEY_CHANNELUP);
329
1
    retString = useful_F_libs::read_from_mkfifo(test_omxplayerFile.c_str());
330
1
    std::cout << "DUPA: " << retString.size() << std::endl;
331
1
   // EXPECT_EQ(retString,"o");
332
1
333
1
    test_irda->_add(PILOT_KEY::KEY_CHANNELDOWN);
334
1
    retString = useful_F_libs::read_from_mkfifo(test_omxplayerFile.c_str());
335
1
    std::cout << "DUPA: " << retString.size() << std::endl;
336
1
   // EXPECT_EQ(retString,"i");
337
1
338
1
    test_my_data.ptr_MPD_info->isPlay = true;
339
1
    test_irda->_add(PILOT_KEY::KEY_EXIT);
340
1
    retString = useful_F_libs::read_from_mkfifo(test_omxplayerFile.c_str());
341
1
    std::cout << "DUPA: " << retString.size() << std::endl;
342
1
    EXPECT_EQ(test_irda->who, PILOT_STATE::MPD);
343
1
344
1
    test_my_data.ptr_MPD_info->isPlay = false;
345
1
    test_irda->_add(PILOT_KEY::KEY_EXIT);
346
1
    retString = useful_F_libs::read_from_mkfifo(test_omxplayerFile.c_str());
347
1
    std::cout << "DUPA: " << retString.size() << std::endl;
348
1
    EXPECT_EQ(test_irda->who, PILOT_STATE::MPD);
349
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("speakers"),STATE::OFF);
350
1
351
1
    //// dummy
352
1
    test_irda->who = PILOT_STATE::PROJECTOR;
353
1
    test_irda->_add(PILOT_KEY::KEY_0);
354
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/c_connection/c_connection2.cpp
Line
Count
Source
1
#include "c_connection.h"
2
#include <iostream>
3
4
std::string C_connection::c_read_buf (int recvSize)
5
3
{
6
3
    std::string str_buf;
7
34
    for (int i = 0; i < recvSize; ++i)
8
31
    {
9
31
        str_buf.push_back( c_buffer[i]);
10
31
    }
11
3
    crypto(str_buf,m_encriptionKey,m_encrypted);
12
3
    return str_buf;
13
3
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/command.cpp
Line
Count
Source
1
#include "command.h"
2
3
command::command(const std::string &commandName ) : commandName(commandName)
4
266
{
5
266
   // std::cout << "konstruktor command"<<std::endl;
6
266
}
7
8
command::~command()
9
266
{
10
266
  // puts("command::~command()");
11
266
}
12
13
std::string command::getCommandName()
14
156
{
15
156
    return commandName;
16
156
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/c_connection/c_connection_node.cpp
Line
Count
Source
1
2
#include "c_connection.h"
3
#include <iostream>
4
5
//////// not used now
6
//void C_connection::c_start_master ()
7
//{
8
//    std::cout << " w pamieci jest " <<my_data->server_settings->AAS.size() <<" nodow\n";
9
//    for (unsigned int i =0; i<my_data->server_settings->AAS.size(); ++i )
10
//    {
11
//        std::cout << " jest ustawien id " << my_data->server_settings->AAS[i].id << std::endl;
12
//        std::cout << " jest ustawien ip " << my_data->server_settings->AAS[i].SERVER_IP << std::endl;
13
//    }
14
//        while (1)
15
//        {
16
//             //c_recv_master_to();
17
//             c_recv_send_master();
18
//             std::cout << " odebralem w masterze \n";
19
//             //c_send_master_to(c_bufor_tmp[16]);
20
//        }
21
//}
22
23
24
//void C_connection::c_recv_send_master()
25
//{
26
//    while (1)
27
//    {
28
//        std::this_thread::sleep_for( std::chrono::milliseconds(50) );
29
30
//        mutex_who.lock();
31
//        if (pointer->ptr_who[0] == my_data->server_settings->ID_server)
32
//        {
33
//            mutex_buf.lock();
34
35
//            for (int i =0; i < MAX_MSG_LEN; ++i )
36
//            {
37
//                 pointer->ptr_buf[i]-=1;
38
//            }
39
//            pointer->ptr_who[0] = pointer->ptr_who[1];
40
//            pointer->ptr_who[1] = my_data->server_settings->ID_server;
41
//            mutex_buf.unlock();
42
//        }
43
//         mutex_who.unlock();
44
//    } // end while
45
//}
46
47
void C_connection::setEncriptionKey(const std::string& key)
48
1
{
49
1
    m_encriptionKey = key;
50
1
}
51
52
void C_connection::setEncrypted(bool flag)
53
4
{
54
4
    m_encrypted = flag;
55
4
}
56
57
void C_connection::crypto(std::string &toEncrypt, std::string key, bool encrypted)
58
9
{
59
9
    if (!encrypted){
60
5
          return;
61
5
      }
62
9
    unsigned int keySize = key.size()-1;
63
4
#ifdef BT_TEST
64
4
    std::cout << "key: " << key << " size: " << key.size() << std::endl;
65
4
#endif
66
74
    for (unsigned int i = 0; i < toEncrypt.size (); i++)
67
70
    {
68
70
        if (keySize == 0)
69
70
            keySize = key.size()-1;
70
70
        else
71
70
            --keySize;
72
70
        toEncrypt[i] ^= key[keySize];
73
70
    }
74
4
}
75
76
void C_connection::onStartConnection()
77
8
{
78
8
//    log_file_mutex.mutex_lock();
79
8
//    log_file_cout << INFO<< "konstruuje nowy obiekt do komunikacj na gniezdzie " << c_socket << std::endl;
80
8
//    log_file_mutex.mutex_unlock();
81
8
}
82
83
void C_connection::onStopConnection()
84
1
{
85
1
    my_data->main_iDomTools->cameraLedOFF(my_data->server_settings->cameraLedOFF);
86
1
}
87
88
void C_connection::cryptoLog(std::string &toEncrypt)
89
2
{
90
2
    crypto(toEncrypt,m_encriptionKey,m_encrypted);
91
2
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_433mhz_BT.cpp
Line
Count
Source
1
#include "../command_433mhz.h"
2
#include "../../../functions/functions.h"
3
#include "../../../RADIO_433_eq/radio_433_eq.h"
4
#include "../../../433MHz/RFLink/rflinkhandler.h"
5
#include "../../../iDomTools/test/iDomTools_fixture.h"
6
7
class command433MHz_Class_fixture : public iDomTOOLS_ClassTest
8
{
9
public:
10
    command433MHz_Class_fixture()
11
13
    {
12
13
        this->test_command_433MHz = std::nullptr_t();
13
13
        this->test_RFLink = std::nullptr_t();
14
13
    }
15
16
protected:
17
    std::vector<std::string> test_v= {"433MHz"};
18
    RFLinkHandler* test_RFLink;
19
    blockQueue test_q;
20
    command_433MHz* test_command_433MHz;
21
22
    void SetUp() final
23
13
    {
24
13
        iDomTOOLS_ClassTest::SetUp();
25
13
26
13
        test_q._clearAll();
27
13
28
13
        test_RFLink = new RFLinkHandler(&test_my_data);
29
13
        test_command_433MHz = new command_433MHz("433MHz");
30
13
        test_my_data.main_RFLink = test_RFLink;
31
13
        std::cout << "command433MHz_Class_fixture SetUp" << std::endl;
32
13
    }
33
34
    void TearDown() final
35
13
    {
36
13
        iDomTOOLS_ClassTest::TearDown();
37
13
        delete test_RFLink;
38
13
        delete test_command_433MHz;
39
13
        std::cout << "command433MHz_Class_fixture TearDown" << std::endl;
40
13
    }
41
42
    void addSwitch(const std::string& name)
43
1
    {
44
1
        test_v.clear();
45
1
        test_v.push_back("433MHz");
46
1
        test_v.push_back("add");
47
1
        test_v.push_back("SWITCH");
48
1
        test_v.push_back(name);
49
1
        test_v.push_back("1234");
50
1
        test_v.push_back("onCode_A");
51
1
        test_v.push_back("ofCode_A");
52
1
        test_v.push_back("on15sec_A");
53
1
        test_v.push_back("sunrise_A");
54
1
        test_v.push_back("sunset_A");
55
1
        test_v.push_back("lock_A");
56
1
        test_v.push_back("unlock_A");
57
1
        std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
58
1
    }
59
    void deleteSwitch(const std::string& name)
60
2
    {
61
2
        test_v.clear();
62
2
        test_v.push_back("433MHz");
63
2
        test_v.push_back("delete");
64
2
        test_v.push_back(name);
65
2
        std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
66
2
    }
67
};
68
TEST_F(command433MHz_Class_fixture, getCommandName)
69
1
{
70
1
    EXPECT_THAT(test_command_433MHz->getCommandName(),testing::HasSubstr("433MHz"));
71
1
}
72
73
TEST_F(command433MHz_Class_fixture, deleteSwitch)
74
1
{
75
1
    test_v.push_back("show");
76
1
    test_v.push_back("all");
77
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
78
1
    auto v = test_rec->getSwitchPointerVector();
79
1
    EXPECT_EQ(v.size(),5);
80
1
    test_v.clear();
81
1
    test_v.push_back("433MHz");
82
1
    test_v.push_back("delete");
83
1
    test_v.push_back("A");
84
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
85
1
    v = test_rec->getSwitchPointerVector();
86
1
    EXPECT_EQ(v.size(),4);
87
1
    test_v.clear();
88
1
    test_v.push_back("433MHz");
89
1
    test_v.push_back("show");
90
1
    test_v.push_back("all");
91
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
92
1
    addSwitch("A");
93
1
94
1
}
95
TEST_F(command433MHz_Class_fixture, deleteFakeSwitch)
96
1
{
97
1
    int actualSize = test_rec->getSwitchPointerVector().size();
98
1
    test_v.push_back("show");
99
1
    test_v.push_back("all");
100
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
101
1
    auto v = test_rec->getSwitchPointerVector();
102
1
    EXPECT_EQ(v.size(),actualSize);
103
1
    test_v.clear();
104
1
    test_v.push_back("433MHz");
105
1
    test_v.push_back("delete");
106
1
    test_v.push_back("fake");
107
1
    std::string result = test_command_433MHz->execute(test_v,&test_my_data);
108
1
    EXPECT_THAT(result, testing::HasSubstr("not exist"));
109
1
    v = test_rec->getSwitchPointerVector();
110
1
    EXPECT_EQ(v.size(),actualSize);
111
1
    test_v.clear();
112
1
    test_v.push_back("433MHz");
113
1
    test_v.push_back("show");
114
1
    test_v.push_back("all");
115
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
116
1
}
117
TEST_F(command433MHz_Class_fixture, addButton)
118
1
{
119
1
    int actualSize = test_rec->getButtonPointerVector().size();
120
1
    test_v.push_back("show");
121
1
    test_v.push_back("all");
122
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
123
1
    auto v = test_rec->getButtonPointerVector();
124
1
    EXPECT_EQ(v.size(),actualSize);
125
1
    test_v.clear();
126
1
    test_v.push_back("433MHz");
127
1
    test_v.push_back("add");
128
1
    test_v.push_back("BUTTON");
129
1
    test_v.push_back("glowny");
130
1
    test_v.push_back("4321");
131
1
    test_v.push_back("onCode");
132
1
    test_v.push_back("offCode");
133
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
134
1
    v = test_rec->getButtonPointerVector();
135
1
    EXPECT_EQ(v.size(),actualSize+1);
136
1
    test_v.clear();
137
1
    test_v.push_back("433MHz");
138
1
    test_v.push_back("show");
139
1
    test_v.push_back("all");
140
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
141
1
    deleteSwitch("glowny");
142
1
}
143
144
TEST_F(command433MHz_Class_fixture, addSwitch)
145
1
{
146
1
    int actualSize = test_rec->getSwitchPointerVector().size();
147
1
    test_v.push_back("show");
148
1
    test_v.push_back("all");
149
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
150
1
    auto v = test_rec->getSwitchPointerVector();
151
1
    EXPECT_EQ(v.size(),actualSize);
152
1
    test_v.clear();
153
1
    test_v.push_back("433MHz");
154
1
    test_v.push_back("add");
155
1
    test_v.push_back("SWITCH");
156
1
    test_v.push_back("Aaa");
157
1
    test_v.push_back("1234");
158
1
    test_v.push_back("onCode_A");
159
1
    test_v.push_back("ofCode_A");
160
1
    test_v.push_back("on15sec_A");
161
1
    test_v.push_back("sunrise_A");
162
1
    test_v.push_back("sunset_A");
163
1
    test_v.push_back("lock_A");
164
1
    test_v.push_back("unlock_A");
165
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
166
1
    v = test_rec->getSwitchPointerVector();
167
1
    EXPECT_EQ(v.size(),actualSize+1);
168
1
    test_v.clear();
169
1
    test_v.push_back("433MHz");
170
1
    test_v.push_back("show");
171
1
    test_v.push_back("all");
172
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
173
1
    deleteSwitch("Aaa");
174
1
}
175
176
TEST_F(command433MHz_Class_fixture, addExistingWeather)
177
1
{
178
1
    test_v.push_back("show");
179
1
    test_v.push_back("all");
180
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
181
1
    auto v = test_rec->getWeather_StationPtrVector();
182
1
    EXPECT_EQ(v.size(),1);
183
1
    test_v.clear();
184
1
    test_v.push_back("433MHz");
185
1
    test_v.push_back("add");
186
1
    test_v.push_back("WEATHER");
187
1
    test_v.push_back("first");
188
1
    test_v.push_back("1234");
189
1
190
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
191
1
    v = test_rec->getWeather_StationPtrVector();
192
1
    EXPECT_EQ(v.size(),1);
193
1
    test_v.clear();
194
1
    test_v.push_back("433MHz");
195
1
    test_v.push_back("show");
196
1
    test_v.push_back("all");
197
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
198
1
}
199
200
TEST_F(command433MHz_Class_fixture, missingParamiter_addSwitch)
201
1
{
202
1
    test_v.push_back("show");
203
1
    test_v.push_back("all");
204
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
205
1
    auto v = test_rec->getSwitchPointerVector();
206
1
    EXPECT_EQ(v.size(),5);
207
1
    test_v.clear();
208
1
    test_v.push_back("433MHz");
209
1
    test_v.push_back("add");
210
1
    test_v.push_back("SWITCH");
211
1
    test_v.push_back("Abc");
212
1
    test_v.push_back("1234");
213
1
    test_v.push_back("onCode_A");
214
1
    test_v.push_back("ofCode_A");
215
1
    test_v.push_back("on15sec_A");
216
1
    std::string result = test_command_433MHz->execute(test_v,&test_my_data);
217
2
    EXPECT_THAT(result, testing::HasSubstr("mising paramiter")) << "nie ma bledu";
218
1
    v = test_rec->getSwitchPointerVector();
219
1
    EXPECT_EQ(v.size(),5);
220
1
    test_v.clear();
221
1
    test_v.push_back("433MHz");
222
1
    test_v.push_back("show");
223
1
    test_v.push_back("all");
224
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
225
1
}
226
\
227
TEST_F(command433MHz_Class_fixture, add_wrongType_addSwitch)
228
1
{
229
1
    test_v.push_back("show");
230
1
    test_v.push_back("all");
231
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
232
1
    auto v = test_rec->getSwitchPointerVector();
233
1
    EXPECT_EQ(v.size(),5);
234
1
    test_v.clear();
235
1
    test_v.push_back("433MHz");
236
1
    test_v.push_back("add");
237
1
    test_v.push_back("FAKE"); //here is wrong type
238
1
    test_v.push_back("Abc");
239
1
    test_v.push_back("1234");
240
1
    test_v.push_back("onCode_A");
241
1
    test_v.push_back("ofCode_A");
242
1
    test_v.push_back("on15sec_A");
243
1
    test_v.push_back("sunrise_A");
244
1
    test_v.push_back("sunset_A");
245
1
    test_v.push_back("lock_A");
246
1
    test_v.push_back("unlock_A");
247
1
    std::string result = test_command_433MHz->execute(test_v,&test_my_data);
248
1
    EXPECT_THAT(result, testing::HasSubstr("wrong type"));
249
1
    std::cout << "wynik testu: " << result << std::endl;
250
1
    v = test_rec->getSwitchPointerVector();
251
1
    EXPECT_EQ(v.size(),5);
252
1
    test_v.clear();
253
1
    test_v.push_back("433MHz");
254
1
    test_v.push_back("show");
255
1
    test_v.push_back("all");
256
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
257
1
}
258
259
TEST_F(command433MHz_Class_fixture, add_wrongID_addSwitch)
260
1
{
261
1
    test_v.push_back("show");
262
1
    test_v.push_back("all");
263
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
264
1
    auto v = test_rec->getSwitchPointerVector();
265
1
    EXPECT_EQ(v.size(),5);
266
1
    test_v.clear();
267
1
    test_v.push_back("433MHz");
268
1
    test_v.push_back("add");
269
1
    test_v.push_back("SWITCH");
270
1
    test_v.push_back("Abc");
271
1
    test_v.push_back("dummy"); //here is wrong ID
272
1
    test_v.push_back("onCode_A");
273
1
    test_v.push_back("ofCode_A");
274
1
    test_v.push_back("on15sec_A");
275
1
    test_v.push_back("sunrise_A");
276
1
    test_v.push_back("sunset_A");
277
1
    test_v.push_back("lock_A");
278
1
    test_v.push_back("unlock_A");
279
1
    std::string result = test_command_433MHz->execute(test_v,&test_my_data);
280
1
    std::cout << "wynik testu: " << result << std::endl;
281
1
    EXPECT_THAT(result, testing::HasSubstr("wrong ID"));
282
1
    v = test_rec->getSwitchPointerVector();
283
1
    EXPECT_EQ(v.size(),5);
284
1
    test_v.clear();
285
1
    test_v.push_back("433MHz");
286
1
    test_v.push_back("show");
287
1
    test_v.push_back("all");
288
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
289
1
}
290
291
TEST_F(command433MHz_Class_fixture, show_switch)
292
1
{
293
1
    test_v.push_back("show");
294
1
    test_v.push_back("all");
295
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
296
1
    auto v = test_rec->getSwitchPointerVector();
297
1
    EXPECT_EQ(v.size(),5);
298
1
    test_v.clear();
299
1
    test_v.push_back("433MHz");
300
1
    test_v.push_back("show");
301
1
    test_v.push_back("switch");
302
1
303
1
    std::string result = test_command_433MHz->execute(test_v,&test_my_data);
304
1
    std::cout << "wynik testu: " << result << std::endl;
305
1
    EXPECT_THAT(result, testing::HasSubstr("UNDEFINE"));
306
1
    v = test_rec->getSwitchPointerVector();
307
1
    EXPECT_EQ(v.size(),5);
308
1
    test_v.clear();
309
1
    test_v.push_back("433MHz");
310
1
    test_v.push_back("show");
311
1
    test_v.push_back("all");
312
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
313
1
}
314
315
TEST_F(command433MHz_Class_fixture, show_aether)
316
1
{
317
1
    test_my_data.main_RFLink->rflinkMAP["kk"].msg = "astro";
318
1
    test_my_data.main_RFLink->rflinkMAP["kk"].m_counter = 99;
319
1
    test_my_data.main_RFLink->rflinkMAP["jj"].msg = "lock";
320
1
    test_my_data.main_RFLink->rflinkMAP["jj"].m_counter = 155;
321
1
    test_v.push_back("show");
322
1
    test_v.push_back("all");
323
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
324
1
    auto v = test_rec->getSwitchPointerVector();
325
1
    EXPECT_EQ(v.size(),5);
326
1
    test_v.clear();
327
1
    test_v.push_back("433MHz");
328
1
    test_v.push_back("show");
329
1
    test_v.push_back("aether");
330
1
331
1
    std::string result = test_command_433MHz->execute(test_v,&test_my_data);
332
1
    std::cout << "wynik testu: " << result << std::endl;
333
1
    EXPECT_THAT(result, testing::HasSubstr("astro"));
334
1
    EXPECT_THAT(result, testing::HasSubstr("lock"));
335
1
    EXPECT_THAT(result, testing::HasSubstr("99"));
336
1
    EXPECT_THAT(result, testing::HasSubstr("155"));
337
1
    v = test_rec->getSwitchPointerVector();
338
1
    EXPECT_EQ(v.size(),5);
339
1
    test_v.clear();
340
1
}
341
342
TEST_F(command433MHz_Class_fixture, switchRF433)
343
1
{
344
1
    test_v.push_back("show");
345
1
    test_v.push_back("all");
346
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
347
1
    auto v = test_rec->getSwitchPointerVector();
348
1
    EXPECT_EQ(v.size(),5);
349
1
    /////////////////////////////// ON
350
1
    test_v.clear();
351
1
    test_v.push_back("433MHz");
352
1
    test_v.push_back("switch");
353
1
    test_v.push_back("B");
354
1
    test_v.push_back("ON");
355
1
    test_command_433MHz->execute(test_v,&test_my_data);
356
1
    EXPECT_EQ(test_my_data.main_REC->getEqPointer("B")->getState(), STATE::ON);
357
1
    ////////////////////////////// OFF
358
1
    test_v.clear();
359
1
    test_v.push_back("433MHz");
360
1
    test_v.push_back("switch");
361
1
    test_v.push_back("B");
362
1
    test_v.push_back("OFF");
363
1
    test_command_433MHz->execute(test_v,&test_my_data);
364
1
    EXPECT_EQ(test_my_data.main_REC->getEqPointer("B")->getState(), STATE::OFF);
365
1
    ////////////////////////////// 15s
366
1
    test_v.clear();
367
1
    test_v.push_back("433MHz");
368
1
    test_v.push_back("switch");
369
1
    test_v.push_back("B");
370
1
    test_v.push_back("15s");
371
1
    test_command_433MHz->execute(test_v,&test_my_data);
372
1
    EXPECT_EQ(test_my_data.main_REC->getEqPointer("B")->getState(), STATE::WORKING);
373
1
    ////////////////////////////// unknown paramiter
374
1
    test_v.clear();
375
1
    test_v.push_back("433MHz");
376
1
    test_v.push_back("switch");
377
1
    test_v.push_back("B");
378
1
    test_v.push_back("fake");
379
1
    std::string result = test_command_433MHz->execute(test_v,&test_my_data);
380
1
    EXPECT_EQ(test_my_data.main_REC->getEqPointer("B")->getState(), STATE::WORKING);
381
1
    EXPECT_THAT(result, testing::HasSubstr("fake"));
382
1
    ///////////////////////////// fake switch
383
1
    test_v.clear();
384
1
    test_v.push_back("433MHz");
385
1
    test_v.push_back("switch");
386
1
    test_v.push_back("B_fake");
387
1
    test_v.push_back("fake");
388
1
389
1
    result = test_command_433MHz->execute(test_v,&test_my_data);
390
1
    EXPECT_THAT(result, testing::HasSubstr("not found"));
391
1
    v = test_rec->getSwitchPointerVector();
392
1
    EXPECT_EQ(v.size(),5);
393
1
    test_v.clear();
394
1
}
395
396
TEST_F(command433MHz_Class_fixture, sendRF433)
397
1
{
398
1
    test_v.push_back("show");
399
1
    test_v.push_back("all");
400
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
401
1
    auto v = test_rec->getSwitchPointerVector();
402
1
    EXPECT_EQ(v.size(),5);
403
1
    test_v.clear();
404
1
    test_v.push_back("433MHz");
405
1
    test_v.push_back("send");
406
1
    test_v.push_back("fake");
407
1
408
1
     std::string retStr = test_command_433MHz->execute(test_v,&test_my_data);
409
1
    EXPECT_THAT(retStr, testing::HasSubstr("sended"));
410
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/c_connection/c_connection.h
Line
Count
Source
1
#ifndef C_CONNECTION_H
2
#define C_CONNECTION_H
3
#include <mutex>
4
#include <unistd.h>
5
#include <iostream>
6
#include "../functions/functions.h"
7
#include "../CRON/cron.hpp"
8
#include "../functions/mpd_cli.h"
9
#include "../command/commandhandlerroot.h"
10
#include "../iDom_server_OOP.h"
11
12
constexpr int MAX_buf = 32768;
13
14
class C_connection
15
{
16
#ifdef BT_TEST
17
   friend class c_connection_fixture;
18
#endif
19
public:
20
    C_connection(thread_data *my_data);
21
    ~C_connection();
22
23
    thread_data *my_data;
24
    int c_socket;
25
    sockaddr_in c_from;
26
27
    char c_buffer[MAX_buf];
28
    int recv_size;
29
    struct s_pointer *pointer;
30
31
    int c_send(int para);
32
    int c_send(const std::string& command);
33
    int c_recv(int para);
34
    std::string c_read_buf(int recvSize);
35
    void c_analyse(int recvSize);
36
    void setEncriptionKey(const std::string& key);
37
    void setEncrypted(bool flag);
38
    commandHandler *mainCommandHandler = NULL;
39
    void onStartConnection();
40
    void onStopConnection();
41
    void cryptoLog(std::string &toEncrypt);
42
#ifdef BT_TEST
43
1
    std::string getStr_buf(){
44
1
        return str_buf;
45
1
    }
46
#endif
47
private:
48
    std::string str_buf;
49
    blockQueue char_queue;
50
    int counter = 0;
51
    std::string m_encriptionKey;
52
    bool m_encrypted;
53
    void crypto(std::string &toEncrypt, std::string key, bool encrypted);
54
};
55
56
#endif // C_CONNECTION_H
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_ardu_BT.cpp
Line
Count
Source
1
#include <gtest/gtest.h>
2
#include "../command_ardu.h"
3
#include "../../../functions/functions.h"
4
#include "../../../RADIO_433_eq/radio_433_eq.h"
5
#include "../../../433MHz/RFLink/rflinkhandler.h"
6
#include "../../../iDomTools/test/iDomTools_fixture.h"
7
8
class commandArdu_Class_fixture : public iDomTOOLS_ClassTest
9
{
10
public:
11
11
    commandArdu_Class_fixture() {
12
11
        this->test_RFLink = std::nullptr_t();
13
11
        this->test_ardu = std::nullptr_t();
14
11
    }
15
16
protected:
17
    std::vector<std::string> test_v= {"ardu"};
18
    RFLinkHandler* test_RFLink;
19
    blockQueue test_q;
20
    command_ardu* test_ardu;
21
    void SetUp() final
22
11
    {
23
11
        iDomTOOLS_ClassTest::SetUp();
24
11
25
11
        test_q._clearAll();
26
11
27
11
        test_RFLink = new RFLinkHandler(&test_my_data);
28
11
        test_ardu = new command_ardu("ardu", &test_my_data);
29
11
        test_my_data.main_RFLink = test_RFLink;
30
11
        test_v.push_back("433MHz");
31
11
        std::cout << "commandArdu_Class_fixture SetUp" << std::endl;
32
11
    }
33
34
    void TearDown() final
35
11
    {
36
11
        iDomTOOLS_ClassTest::TearDown();
37
11
        delete test_RFLink;
38
11
        delete test_ardu;
39
11
        std::cout << "commandArdu_Class_fixture TearDown" << std::endl;
40
11
    }
41
42
};
43
44
TEST_F(commandArdu_Class_fixture, wrongMSGformat)
45
1
{
46
1
    test_v.push_back("EV1527;ID=01e7be;SWITCH=01;CMD=ON;"); // wronh msg format missing 20;
47
1
    EXPECT_THROW(test_ardu->execute(test_v, &test_my_data), WRONG_FORMAT);
48
1
}
49
50
TEST_F(commandArdu_Class_fixture, UnlockHome)
51
1
{
52
1
    test_idomTOOLS->lockHome();
53
1
    EXPECT_EQ(test_status.getObjectState("house"),STATE::LOCK);
54
1
55
1
    test_v.push_back("20;EV1527;ID=01e7be;SWITCH=01;CMD=ON;");
56
1
    test_ardu->execute(test_v, &test_my_data);
57
1
    EXPECT_EQ(test_status.getObjectState("house"),STATE::UNLOCK);
58
1
59
1
    EXPECT_EQ(test_q._size(),1);
60
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::PLAY);
61
1
    EXPECT_EQ(test_q._size(),0);
62
1
}
63
64
TEST_F(commandArdu_Class_fixture, LockHome)
65
1
{
66
1
    test_idomTOOLS->unlockHome();
67
1
    EXPECT_EQ(test_status.getObjectState("house"),STATE::UNLOCK);
68
1
69
1
    test_v.push_back("20;EV1527;ID=01e7be;SWITCH=01;CMD=ON;");
70
4
    for(auto i = 0; i < 3; ++i){
71
3
        test_ardu->execute(test_v, &test_my_data);
72
3
    }
73
1
74
1
    EXPECT_EQ(test_status.getObjectState("house"),STATE::LOCK);
75
1
    EXPECT_EQ(test_q._size(),1);
76
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::STOP);
77
1
    EXPECT_EQ(test_q._size(),0);
78
1
}
79
80
TEST_F(commandArdu_Class_fixture, playMusic)
81
1
{
82
1
    test_idomTOOLS->unlockHome();
83
1
    EXPECT_EQ(test_status.getObjectState("house"),STATE::UNLOCK);
84
1
    EXPECT_EQ(test_status.getObjectState("listwa"),STATE::UNKNOWN);
85
1
    test_status.addObject("music",STATE::STOP);
86
1
87
1
    test_v.push_back("20;EV1527;ID=01e7be;SWITCH=01;CMD=ON;");
88
1
89
1
    test_ardu->execute(test_v, &test_my_data);
90
1
91
1
    EXPECT_EQ(test_q._size(),1);
92
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::PLAY);
93
1
    EXPECT_EQ(test_q._size(),0);
94
1
    EXPECT_EQ(test_status.getObjectState("listwa"),STATE::ON);
95
1
}
96
97
TEST_F(commandArdu_Class_fixture, stopMusic)
98
1
{
99
1
    test_idomTOOLS->unlockHome();
100
1
    EXPECT_EQ(test_status.getObjectState("house"),STATE::UNLOCK);
101
1
    EXPECT_EQ(test_status.getObjectState("listwa"),STATE::UNKNOWN);
102
1
    test_status.addObject("music",STATE::PLAY);
103
1
104
1
    test_v.push_back("20;EV1527;ID=01e7be;SWITCH=01;CMD=ON;");
105
1
106
1
    test_ardu->execute(test_v, &test_my_data);
107
1
108
1
    EXPECT_EQ(test_q._size(),1);
109
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::STOP);
110
1
    EXPECT_EQ(test_q._size(),0);
111
1
    EXPECT_EQ(test_status.getObjectState("listwa"),STATE::OFF);
112
1
}
113
114
TEST_F(commandArdu_Class_fixture, weatherStationTemp)
115
1
{
116
1
    test_v.push_back("20;2A;LaCrosse;ID=0704;TEMP=8043;");
117
1
    test_ardu->execute(test_v, &test_my_data);
118
1
    RADIO_WEATHER_STATION* st = static_cast<RADIO_WEATHER_STATION*>(test_my_data.main_REC->getEqPointer("first"));
119
1
    EXPECT_DOUBLE_EQ(-6.7, st->data.getTemperature() );
120
1
    EXPECT_DOUBLE_EQ(0, st->data.getHumidity() );
121
1
    test_v[2] = "20;35;LaCrosse;ID=0704;HUM=42;";
122
1
    test_ardu->execute(test_v, &test_my_data);
123
1
    EXPECT_DOUBLE_EQ(42, st->data.getHumidity() );
124
1
    test_v[2] = "20;2A;LaCrosse;ID=0704;TEMP=0000;";
125
1
    test_ardu->execute(test_v, &test_my_data);
126
1
    EXPECT_DOUBLE_EQ(0, st->data.getTemperature() );
127
1
}
128
129
TEST_F(commandArdu_Class_fixture, command_ardu_show)
130
1
{
131
1
    test_v.pop_back();
132
1
    test_v.push_back("show");
133
1
    std::string retStr = test_ardu->execute(test_v, &test_my_data);
134
1
    EXPECT_THAT(retStr, testing::HasSubstr("data: 0"));
135
1
    EXPECT_THAT(retStr, testing::HasSubstr("temperature= 0c"));
136
1
}
137
138
TEST_F(commandArdu_Class_fixture, command_ardu_help)
139
1
{
140
1
    command_ardu test_Command_ardu ("ardu");
141
1
142
1
    std::string retStr = test_Command_ardu.help();
143
1
    EXPECT_STREQ(retStr.c_str(), " only for internal usege\n");
144
1
}
145
146
TEST_F(commandArdu_Class_fixture, command_ardu_433MHz_throw)
147
1
{
148
1
    test_v.push_back("fake_msg");
149
1
    std::string retStr = test_ardu->execute(test_v, &test_my_data);
150
1
151
1
    EXPECT_THAT(retStr, testing::HasSubstr("for"));
152
1
}
153
154
TEST_F(commandArdu_Class_fixture, command_ardu_433MHz_OK)
155
1
{
156
1
    test_v.push_back("20;53;OK;");
157
1
    test_ardu->execute(test_v, &test_my_data);
158
1
    EXPECT_NE(test_my_data.main_RFLink->okTime, 0);
159
1
    EXPECT_EQ(test_my_data.main_RFLink->okTime, Clock::getUnixTime());
160
1
}
161
162
TEST_F(commandArdu_Class_fixture, command_ardu_433MHz_PING)
163
1
{
164
1
    test_v.push_back("20;99;PONG;");
165
1
    test_ardu->execute(test_v, &test_my_data);
166
1
    EXPECT_NE(test_my_data.main_RFLink->pingTime, 0);
167
1
    EXPECT_EQ(test_my_data.main_RFLink->pingTime, Clock::getUnixTime());
168
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/c_connection/test/c_connection_BT.cpp
Line
Count
Source (jump to first uncovered line)
1
#include <gtest/gtest.h>
2
#include "../../iDomTools/test/iDomTools_fixture.h"
3
4
#include "../c_connection.h"
5
6
class c_connection_fixture : public iDomTOOLS_ClassTest
7
{
8
public:
9
8
    c_connection_fixture():test_connection(std::nullptr_t()) {
10
8
    }
11
12
protected:
13
    std::unique_ptr<C_connection> test_connection;
14
    void SetUp() final
15
8
    {
16
8
        std::cout << "c_connection_fixture SetUp()" << std::endl;
17
8
        iDomTOOLS_ClassTest::SetUp();
18
8
        test_connection = std::make_unique<C_connection>(&test_my_data);
19
8
        test_connection->m_encriptionKey = "key";
20
8
        test_connection->m_encrypted = false;
21
8
        test_connection->c_socket = 0;
22
8
    }
23
    void TearDown() final
24
8
    {
25
8
        iDomTOOLS_ClassTest::TearDown();
26
8
        std::cout << "c_connection_fixture TearDown()" << std::endl;
27
8
    }
28
    void crypto_fixture(std::string &toEncrypt, std::string key)
29
2
    {
30
2
        test_connection->crypto(toEncrypt, std::move(key), true);
31
2
    }
32
};
33
34
TEST_F(c_connection_fixture, crypto)
35
1
{
36
1
    std::string key = "210116556";
37
1
    std::string test_msg = "kokosowa ksiezniczka";
38
1
    std::string toEncrypt = test_msg;
39
1
    crypto_fixture(toEncrypt, key);
40
1
41
21
    for(int i = 0; i < toEncrypt.size(); ++i)
42
20
    {
43
60
        EXPECT_NE(test_msg[i],toEncrypt[i]) << " niestety równe: " << toEncrypt[i]
44
60
                                            << " na indeksie: " << i;
45
20
    }
46
1
    std::cout << "wiadomość: " << test_msg << " zakodowane: "<< toEncrypt << std::endl;
47
1
    crypto_fixture(toEncrypt, key);
48
1
    std::cout << "wiadomość: " << test_msg << " odkodowane: "<< toEncrypt << std::endl;
49
3
    EXPECT_STREQ(toEncrypt.c_str(), test_msg.c_str()) << "wiadomosci nie są równe";
50
1
}
51
52
TEST_F(c_connection_fixture, c_analyse)
53
1
{
54
1
    commandHandlerRoot* chr = new commandHandlerRoot(&test_my_data);
55
1
    test_connection->mainCommandHandler = chr;
56
1
    int i = 0;
57
1
    std::string strMsg = "fake command";
58
1
    for (char n : strMsg)
59
12
        test_connection->c_buffer[i++] = n;
60
1
    test_connection->setEncrypted(false);
61
1
    test_connection->c_analyse(strMsg.size());
62
1
    EXPECT_THAT(test_my_data.myEventHandler.run("command")->getEvent()
63
1
                ,testing::HasSubstr(strMsg));
64
1
}
65
66
TEST_F(c_connection_fixture, c_recv)
67
1
{
68
1
    EXPECT_EQ(-1, test_connection->c_recv(1));
69
1
}
70
71
TEST_F(c_connection_fixture, c_send)
72
1
{
73
1
    EXPECT_EQ(-1, test_connection->c_send("test"));
74
1
}
75
76
TEST_F(c_connection_fixture, cryptoLog)
77
1
{
78
1
    std::string msg("tajna wiadomosc");
79
1
    std::string msgBackup(msg);
80
1
    test_connection->setEncriptionKey("key_test");
81
1
    test_connection->setEncrypted(true);
82
1
    ///////szyfrowanie
83
1
    test_connection->cryptoLog(msg);
84
1
    EXPECT_STRNE(msgBackup.c_str(), msg.c_str());
85
1
    std::cout << "ZASZUFROWANY: " << msg << std::endl;
86
1
    ////// deszyfracja
87
1
    test_connection->cryptoLog(msg);
88
1
    EXPECT_STREQ(msgBackup.c_str(), msg.c_str());
89
1
}
90
91
TEST_F(c_connection_fixture, onStopConnection)
92
1
{
93
1
    TEST_DATA::return_httpPost = "ok.\n";
94
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("cameraLED"),STATE::UNKNOWN);
95
1
    test_connection->onStopConnection();
96
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("cameraLED"),STATE::OFF);
97
1
}
98
99
TEST_F(c_connection_fixture, exitFlow)
100
1
{
101
1
    commandHandlerRoot* chr = new commandHandlerRoot(&test_my_data);
102
1
    test_connection->mainCommandHandler = chr;
103
1
104
1
    int i = 0;
105
1
    std::string strMsg = "program stop server";
106
1
    for (char n : strMsg)
107
19
        test_connection->c_buffer[i++] = n;
108
1
    test_connection->setEncrypted(false);
109
1
    EXPECT_THROW(test_connection->c_analyse(strMsg.size()),std::string );
110
1
}
111
112
TEST_F(c_connection_fixture, emptyCommand)
113
1
{
114
1
    commandHandlerRoot* chr = new commandHandlerRoot(&test_my_data);
115
1
    test_connection->mainCommandHandler = chr;
116
1
117
1
    int i = 0;
118
1
    std::string strMsg = "";
119
1
    for (char n : strMsg)
120
1
        test_connection->c_buffer[i++] = n;
121
1
    test_connection->setEncrypted(false);
122
1
    test_connection->c_analyse(strMsg.size());
123
    EXPECT_STREQ(test_connection->getStr_buf().c_str(), "empty command");
124
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_big_BT.cpp
Line
Count
Source
1
#include "../command_big.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_big_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_big_Class_fixture()
8
1
    {
9
1
10
1
    }
11
12
protected:
13
    std::unique_ptr<command_big> test_command_big;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
17
1
    {
18
1
        iDomTOOLS_ClassTest::SetUp();
19
1
        test_command_big = std::make_unique <command_big> ("big");
20
1
    }
21
22
    void TearDown() final
23
1
    {
24
1
        iDomTOOLS_ClassTest::TearDown();
25
1
    }
26
};
27
28
TEST_F(command_big_Class_fixture, main)
29
1
{
30
1
    int s = 55;
31
1
    test_v.push_back("big");
32
1
    test_v.push_back(std::to_string(s));
33
1
    auto ret = test_command_big->execute(test_v,&test_my_data);
34
1
    EXPECT_EQ(ret.size(),s);
35
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDom_server_OOP.h
Line
Count
Source
1
#ifndef GLOBAL_H
2
#define GLOBAL_H
3
4
#include <iostream>
5
#include <fstream>
6
#include <string>
7
#include <cstdlib>
8
#include <pthread.h>
9
#include <stdio.h>
10
#include <stdlib.h>
11
#include <sys/socket.h>
12
#include <sys/types.h>
13
#include <netinet/in.h>
14
#include <vector>
15
#include <thread>
16
#include <arpa/inet.h>
17
#include <netinet/in.h>
18
#include <unistd.h>
19
#include <sys/fcntl.h>
20
#include <unistd.h>
21
#include <errno.h>
22
#include <signal.h>
23
#include <time.h>
24
#include <wiringPi.h>
25
#include <chrono>
26
#include <array>
27
28
// MOJE BIBLIOTEKI
29
#include "KEY/key.h"
30
#include "logger/logger.hpp"
31
#include "files_tree/files_tree.h"
32
#include "menu_tree/menu_tree.h"
33
#include "LCD_c/lcd_c.h"
34
#include "command/command.h"
35
#include "../libs/event_counters/event_counters_handler.h"
36
#include "iDomTools/idomtools.h"
37
#include "iDomStatus/idomstatus.h"
38
#include "iDomSaveState/idom_save_state.h"
39
40
42
#define log_file_cout  f_log //std::cout zmien f_log na std::cout i bedzie wypisywac na ekran
41
20
#define log_file_mutex f_log
42
43
enum class iDomStateEnum{
44
    CLOSE = 0,
45
    RELOAD,
46
    ERROR,
47
    WORKING,
48
    HARD_RELOAD
49
};
50
51
namespace iDomConst
52
{
53
constexpr int MAX_CONNECTION = 10;
54
constexpr int FREE  = 1;
55
constexpr int RS232 = 11;
56
constexpr int CLOCK = 12;
57
constexpr int ok    = 0;
58
constexpr int GPIO_SPIK = 21;
59
constexpr int GPIO_PRINTER = 22;
60
constexpr int BUTTON_PIN = 25;
61
}
62
struct ALERT
63
{
64
    Clock time;
65
    STATE state = STATE::DEACTIVE;
66
    unsigned int fromVolume = 48;
67
    unsigned int toVolume = 58;
68
    unsigned int radioID = 8;
69
};
70
71
extern std::string _logfile;
72
extern Logger log_file_mutex;
73
extern std::string buffer;
74
75
enum class TEMPERATURE_STATE;
76
enum class PILOT_KEY;
77
78
struct MPD_info{
79
    std::string title   = "NULL";
80
    std::string radio   = "NULL";
81
    std::string artist  = "NULL";
82
    int volume = 0;
83
    bool isPlay = false;
84
    int currentSongID = 0;
85
    std::vector <std::string> songList = {"NULL"};
86
};
87
struct s_pointer{
88
    unsigned int *ptr_who;
89
    int32_t *ptr_buf;
90
};
91
92
struct Thread_array_struc {
93
    std::thread thread;
94
    std::thread::id thread_ID = std::thread::id(0);
95
    std::string thread_name;
96
    int thread_socket = 0;
97
};
98
99
struct address_another_servers {
100
    int id;
101
    std::string SERVER_IP;
102
};
103
104
struct FTP_SERVER{
105
    std::string URL;
106
    std::string user;
107
    std::string pass;
108
};
109
struct iDOM_STATE{
110
    STATE houseState = STATE::UNDEFINE;
111
112
};
113
114
struct config{
115
    std::string portRS232;
116
    std::string portRS232_clock;
117
    std::string BaudRate;
118
    std::string RFLinkPort;
119
    std::string RFLinkBaudRate;
120
    int PORT;
121
    std::string SERVER_IP;
122
    std::string MPD_IP;
123
    std::string MOVIES_DB_PATH;
124
    std::string MENU_PATH;
125
    std::string THREAD_MPD   = "NULL";
126
    std::string THREAD_IRDA  = "NULL";
127
    std::string THREAD_CRON  = "NULL";
128
    std::string THREAD_RS232 = "NULL";
129
    std::string THREAD_DUMMY = "NULL";
130
    std::string TS_KEY= " gg ";
131
    std::string cameraLedON = "";
132
    std::string cameraLedOFF ="";
133
    std::string cameraURL="";
134
    std::string facebookAccessToken = "";
135
    std::string viberToken = "NULL";
136
    std::string viberAvatar;
137
    std::vector <std::string> viberReceiver;
138
    std::string viberSender;
139
    std::string radio433MHzConfigFile;
140
    std::string omxplayerFile = "NULL";
141
    int ID_server = 0;
142
    int v_delay;
143
    bool encrypted = true;
144
145
    FTP_SERVER ftpServer;
146
    std::string lightningApiURL = "NULL";
147
    std::string saveFilePath = "NULL";
148
};
149
150
struct LED_Strip{
151
    std::string from;
152
    std::string to;
153
    std::string R;
154
    std::string G;
155
    std::string B;
156
    std::string colorName;
157
158
    LED_Strip (int from, int to, int r, int g, int b, std::string colorName = "NULL"):from(std::to_string(from)),
159
        to(std::to_string(to)),
160
        R(std::to_string(r)),
161
        G(std::to_string(g)),
162
        B(std::to_string(b)),
163
        colorName(colorName)
164
    {
165
166
    }
167
    LED_Strip (const std::string& from,
168
               const std::string& to,
169
               const std::string& r,
170
               const std::string& g,
171
               const std::string& b,
172
               const std::string& colorName = "NULL"):
173
        from(from),
174
        to(to),
175
        R(r),
176
        G(g),
177
        B(b),
178
        colorName(colorName)
179
    {
180
181
    }
182
183
    void set (const std::string& from,
184
              const std::string& to,
185
              const std::string& r,
186
              const std::string& g,
187
              const std::string& b,
188
              const std::string& colorName = "NULL")
189
    {
190
        this->from =from;
191
        this->to = to;
192
        R = r;
193
        G = g;
194
        B = b;
195
        this->colorName =colorName;
196
    }
197
198
    void set (int from, int to, int r, int g, int b, std::string colorName = "NULL"){
199
        this->from = std::to_string(from);
200
        this->to = std::to_string(to);
201
        R = std::to_string(r);
202
        G = std::to_string(g);
203
        B = std::to_string(b);
204
        this->colorName =colorName;
205
    }
206
207
    std::string getColorName() const{
208
        return colorName;
209
    }
210
211
    std::string get(unsigned int _from, unsigned int _to) const{
212
        if (_from != 0 || _to != 60){
213
            return "LED:["+std::to_string(_from)+"-"+std::to_string(_to)+"-"+R+"-"+G+"-"+B+"];";
214
        }
215
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
216
    }
217
218
    std::string makeCommand(const std::string& from,
219
                            const std::string& to,
220
                            const std::string& R,
221
                            const std::string& G,
222
                            const std::string& B){
223
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
224
    }
225
};
226
227
struct pilot_led{
228
    unsigned int counter=0;
229
    std::vector<LED_Strip> colorLED   = { LED_Strip(1,60,237,145,33 ,"carrot orange"),
230
                                          LED_Strip(1,60,255,0,0    ,"red"),
231
                                          LED_Strip(1,60,0,255,0    ,"green"),
232
                                          LED_Strip(1,60,0,0,255    ,"blue"),
233
                                          LED_Strip(1,60,255,255,255,"white"),
234
                                          LED_Strip(1,60,255,255,0  ,"yellow"),
235
                                          LED_Strip(1,60,0,255,255  ,"cyan"),
236
                                          LED_Strip(1,60,255,0,255  ,"magenta")
237
                                        };
238
};
239
240
class command; // for struc thread_data req
241
class iDomTOOLS;
242
class RADIO_EQ_CONTAINER;
243
class RFLinkHandler;
244
245
struct thread_data{
246
    int s_client_sock;
247
    struct sockaddr_in from;
248
    struct config *server_settings = NULL;
249
    struct s_pointer pointer;
250
    LCD_c *mainLCD = NULL;
251
    files_tree *main_tree = NULL;
252
    menu_tree *main_MENU = NULL;
253
    iDomTOOLS *main_iDomTools = NULL;
254
    RFLinkHandler *main_RFLink = NULL;
255
    std::array<Thread_array_struc, iDomConst::MAX_CONNECTION> *main_THREAD_arr = NULL;
256
    time_t start;
257
    time_t now_time;
258
    int sleeper;
259
    std::map <std::string, std::unique_ptr <KEY> > key_map;
260
    MPD_info *ptr_MPD_info = NULL;
261
    pilot_led * ptr_pilot_led = NULL;
262
    std::map <std::string, std::unique_ptr<command> >* commandMapPtr = NULL;
263
    event_counters_handler myEventHandler;
264
    std::string encriptionKey = "40%";
265
    iDomSTATUS *main_iDomStatus;
266
    iDOM_STATE idom_all_state;
267
    ALERT alarmTime;
268
    std::shared_ptr<RADIO_EQ_CONTAINER> main_REC;
269
    iDomStateEnum iDomProgramState = iDomStateEnum::WORKING;
270
};
271
272
struct thread_data_rs232{
273
    std::string portRS232;
274
    std::string portRS232_clock;
275
    std::string BaudRate;
276
    struct s_pointer pointer;
277
};
278
279
#endif // GLOBAL_H
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_clock_BT.cpp
Line
Count
Source
1
#include "../command_clock.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_clock_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_clock_Class_fixture()
8
2
    {
9
2
10
2
    }
11
12
protected:
13
    std::unique_ptr<command_clock> test_command_clock;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
17
2
    {
18
2
        iDomTOOLS_ClassTest::SetUp();
19
2
        test_command_clock = std::make_unique <command_clock> ("clock");
20
2
    }
21
22
    void TearDown() final
23
2
    {
24
2
        iDomTOOLS_ClassTest::TearDown();
25
2
    }
26
};
27
28
TEST_F(command_clock_Class_fixture, main)
29
1
{
30
1
    test_v.push_back("clock");
31
1
    test_v.push_back("1234");
32
1
    auto ret = test_command_clock->execute(test_v,&test_my_data);
33
1
    EXPECT_STREQ(ret.c_str(),"clock set return test");
34
1
}
35
36
TEST_F(command_clock_Class_fixture, missingParamiter)
37
1
{
38
1
    test_v.push_back("clock");
39
1
    auto ret = test_command_clock->execute(test_v,&test_my_data);
40
1
    EXPECT_STREQ(ret.c_str(),"can not set clock");
41
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/logger/logger.hpp
Line
Count
Source
1
/*
2
 * logger.hpp
3
 *
4
 *
5
 * Logger Library Header
6
 *
7
 *
8
 * Copyright (C) 2013-2014  Bryant Moscon - bmoscon@gmail.com
9
 *
10
 * Permission is hereby granted, free of charge, to any person obtaining a copy
11
 * of this software and associated documentation files (the "Software"), to
12
 * deal in the Software without restriction, including without limitation the
13
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
14
 * sell copies of the Software, and to permit persons to whom the Software is
15
 * furnished to do so, subject to the following conditions:
16
 *
17
 * 1. Redistributions of source code must retain the above copyright notice,
18
 *    this list of conditions, and the following disclaimer.
19
 *
20
 * 2. Redistributions in binary form must reproduce the above copyright notice,
21
 *    this list of conditions and the following disclaimer in the documentation
22
 *    and/or other materials provided with the distribution, and in the same
23
 *    place and form as other copyright, license and disclaimer information.
24
 *
25
 * 3. The end-user documentation included with the redistribution, if any, must
26
 *    include the following acknowledgment: "This product includes software
27
 *    developed by Bryant Moscon (http://www.bryantmoscon.org/)", in the same
28
 *    place and form as other third-party acknowledgments. Alternately, this
29
 *    acknowledgment may appear in the software itself, in the same form and
30
 *    location as other such third-party acknowledgments.
31
 *
32
 * 4. Except as contained in this notice, the name of the author, Bryant Moscon,
33
 *    shall not be used in advertising or otherwise to promote the sale, use or
34
 *    other dealings in this Software without prior written authorization from
35
 *    the author.
36
 *
37
 *
38
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
41
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
42
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
44
 * THE SOFTWARE.
45
 *
46
 */
47
#ifndef __LOGGER__
48
#define __LOGGER__
49
50
#include <fstream>
51
#include <cassert>
52
#include <ctime>
53
#include <sstream>
54
55
// Log levels
56
typedef enum {
57
    US =0,
58
    VERBOSE,
59
    DEBUG,
60
    INFO,
61
    WARNING,
62
    ERROR,
63
    CRITICAL,
64
    FATAL
65
} logger_level;
66
67
class Logger : public std::ostringstream {
68
public:
69
70
    explicit Logger(const char *f);
71
    explicit Logger(const std::string& f);
72
    Logger (const Logger &);
73
    Logger &operator= (const Logger &);
74
    ~Logger();
75
    static pthread_mutex_t mutex_log;
76
77
    void set_level(const logger_level& level);
78
    void flush();
79
    void mutex_lock();
80
    void mutex_unlock();
81
82
    template <typename T>
83
    Logger& operator<<(const T& t)
84
4
    {
85
4
        *static_cast<std::ostringstream *>(this) << t;
86
4
        return (*this);
87
4
    }
_ZN6LoggerlsIbEERS_RKT_
Line
Count
Source
84
2
    {
85
2
        *static_cast<std::ostringstream *>(this) << t;
86
2
        return (*this);
87
2
    }
_ZN6LoggerlsIA20_cEERS_RKT_
Line
Count
Source
84
2
    {
85
2
        *static_cast<std::ostringstream *>(this) << t;
86
2
        return (*this);
87
2
    }
88
89
    Logger& operator<<(const logger_level& level);
90
    typedef Logger& (* LoggerManip)(Logger&);
91
    Logger& operator<<(LoggerManip m);
92
93
private:
94
    std::string get_time() const;
95
    inline const char* level_str(const logger_level& level);
96
public:
97
    std::ofstream _file;
98
private:
99
    std::ostream& _log;
100
    logger_level _level;
101
    logger_level _line_level;
102
};
103
104
105
namespace std { 
106
inline Logger& endl(Logger& out)
107
{
108
    out.put('\n');
109
    out.flush();
110
    return (out);
111
}
112
}// end namespace std
113
114
#endif
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_cmd_BT.cpp
Line
Count
Source
1
#include "../command_cmd.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_cmd_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_cmd_Class_fixture()
8
2
    {
9
2
10
2
    }
11
12
protected:
13
    std::unique_ptr<command_cmd> test_command_cmd;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
17
2
    {
18
2
        iDomTOOLS_ClassTest::SetUp();
19
2
        test_command_cmd = std::make_unique <command_cmd> ("cmd");
20
2
    }
21
22
    void TearDown() final
23
2
    {
24
2
        iDomTOOLS_ClassTest::TearDown();
25
2
    }
26
};
27
28
TEST_F(command_cmd_Class_fixture, main)
29
1
{
30
1
    test_my_data.server_settings->omxplayerFile = "/mnt/ramdisk/cmd";
31
1
    test_v.push_back("cmd");
32
1
    auto ret = test_command_cmd->execute(test_v,&test_my_data);
33
1
    EXPECT_THAT(ret, ::testing::HasSubstr("fifo file contain:"));
34
1
}
35
36
TEST_F(command_cmd_Class_fixture, wrongParamiter)
37
1
{
38
1
    test_v.push_back("cmd");
39
1
    test_v.push_back("1234");
40
1
    auto ret = test_command_cmd->execute(test_v,&test_my_data);
41
1
    EXPECT_STREQ(ret.c_str(),"error: unknown parameter: 1234");
42
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/c_irda_logic/c_irda_logic.cpp
Line
Count
Source
1
#include "c_irda_logic.h"
2
#include "../iDom_server_OOP.h"
3
#include "../thread_functions/iDom_thread.h"
4
5
void c_irda_logic::irdaMPD(PILOT_KEY X)
6
10
{
7
10
    switch (X){
8
10
    case PILOT_KEY::KEY_POWER:
9
1
        mpd_queue._add(MPD_COMMAND::STOP);
10
1
        break;
11
1
    case PILOT_KEY::KEY_TV:
12
1
        mpd_queue._add(MPD_COMMAND::PLAY);
13
1
        break;
14
1
    case PILOT_KEY::KEY_VOLUMEDOWN:
15
1
        mpd_queue._add(MPD_COMMAND::VOLDOWN);
16
1
        break;
17
1
    case PILOT_KEY::KEY_VOLUMEUP:
18
1
        mpd_queue._add(MPD_COMMAND::VOLUP);
19
1
        break;
20
1
    case PILOT_KEY::KEY_AUDIO:
21
1
        mpd_queue._add(MPD_COMMAND::PAUSE);
22
1
        break;
23
1
    case PILOT_KEY::KEY_UP:
24
1
        mpd_queue._add(MPD_COMMAND::NEXT);
25
1
        break;
26
1
    case PILOT_KEY::KEY_DOWN:
27
1
        mpd_queue._add(MPD_COMMAND::PREV);
28
1
        break;
29
3
    default:
30
3
        log_file_mutex.mutex_lock();
31
3
        log_file_cout << CRITICAL << "nieznana komenda MPD z pilota "<< std::endl;
32
3
        log_file_mutex.mutex_unlock();
33
3
        break;
34
10
    }
35
10
}
36
37
void c_irda_logic::sleeperLogic(PILOT_KEY X)
38
10
{
39
10
    my_data->mainLCD->set_print_song_state(100);
40
10
    my_data->mainLCD->printString(true,0,0,std::to_string(my_data->sleeper)+" minut");
41
10
42
10
    switch (X){
43
10
    case PILOT_KEY::KEY_EXIT:
44
1
    {
45
1
        my_data->sleeper=0;
46
1
        my_data->mainLCD->set_print_song_state(0);
47
1
        who = PILOT_STATE::MPD;
48
1
        break;
49
1
    }
50
4
    case PILOT_KEY::KEY_UP:
51
4
    {
52
4
        ++my_data->sleeper;
53
4
        my_data->mainLCD->printString(true,0,0,std::to_string(my_data->sleeper)+" minut");
54
4
        break;
55
1
    }
56
1
    case PILOT_KEY::KEY_DOWN:
57
1
    {
58
1
        --my_data->sleeper;
59
1
        my_data->mainLCD->printString(true,0,0,std::to_string(my_data->sleeper)+" minut");
60
1
        break;
61
1
    }
62
1
    case PILOT_KEY::KEY_CHANNELUP:
63
1
    {
64
1
        my_data->sleeper+=10;
65
1
        my_data->mainLCD->printString(true,0,0,std::to_string(my_data->sleeper)+" minut");
66
1
        break;
67
1
    }
68
1
    case PILOT_KEY::KEY_CHANNELDOWN:
69
1
    {
70
1
        my_data->sleeper-=10;
71
1
        my_data->mainLCD->printString(true,0,0,std::to_string(my_data->sleeper)+" minut");
72
1
        break;
73
1
    }
74
1
    case PILOT_KEY::KEY_OK:
75
1
    {
76
1
        iDOM_THREAD::start_thread("Sleeper MPD",useful_F::sleeper_mpd,my_data);
77
1
        my_data->mainLCD->printString(true,1,0,"SLEEPer START");
78
1
        my_data->mainLCD->set_print_song_state(0);
79
1
        who = PILOT_STATE::MPD;
80
1
        break;
81
1
    }
82
1
    default:
83
1
        log_file_mutex.mutex_lock();
84
1
        log_file_cout << CRITICAL << "nieznany case w sleeperLogic"<< std::endl;
85
1
        log_file_mutex.mutex_unlock();
86
1
        break;
87
10
    }
88
10
}
89
90
void c_irda_logic::projectorLogic(PILOT_KEY X)
91
12
{
92
12
    my_data->mainLCD->set_print_song_state(100);
93
12
    my_data->mainLCD->printString(false,2,1,"  PROJEKTOR   ");
94
12
95
12
    switch (X)
96
12
    {
97
12
    case PILOT_KEY::KEY_EXIT:
98
2
    {
99
2
        my_data->mainLCD->set_print_song_state(0);
100
2
        who = PILOT_STATE::MPD;
101
2
102
2
        if(my_data->ptr_MPD_info->isPlay == true){
103
1
            iDomTOOLS::MPD_play(my_data);
104
1
        }
105
2
        else {
106
1
            iDomTOOLS::turnOffSpeakers();
107
1
            my_data->mainLCD->set_print_song_state(0); // off display
108
1
            my_data->mainLCD->set_lcd_STATE(0);
109
1
        }
110
2
        break;
111
2
    }
112
2
    case PILOT_KEY::DUMMY:
113
1
    {
114
1
        break;
115
2
    }
116
2
    case PILOT_KEY::KEY_VOLUMEUP:
117
1
    {
118
1
        useful_F_libs::write_to_mkfifo(my_data->server_settings->omxplayerFile, "+");
119
1
        break;
120
2
    }
121
2
    case PILOT_KEY::KEY_VOLUMEDOWN:
122
1
    {
123
1
        useful_F_libs::write_to_mkfifo(my_data->server_settings->omxplayerFile, "-");
124
1
        break;
125
2
    }
126
2
    case PILOT_KEY::KEY_OK:
127
1
    {
128
1
        my_data->mainLCD->set_print_song_state(1000);
129
1
        my_data->mainLCD->printString(false,0,0,"ODTWARZAM VIDEO");
130
1
        useful_F_libs::write_to_mkfifo(my_data->server_settings->omxplayerFile, "p");
131
1
        break;
132
2
    }
133
2
    case PILOT_KEY::KEY_POWER:
134
1
    {
135
1
        //system("echo -n q > /mnt/ramdisk/cmd &"); // zamykanie omxplayera
136
1
        useful_F_libs::write_to_mkfifo(my_data->server_settings->omxplayerFile, "q");
137
1
        break;
138
2
    }
139
2
    case PILOT_KEY::KEY_DOWN:
140
1
    {
141
1
        useful_F::runLinuxCommand("echo -n $'\x1b\x5b\x43' > /mnt/ramdisk/cmd"); // do przodu
142
1
        //write_to_mkfifo("$'\x1b\x5b\x43'");
143
1
        break;
144
2
    }
145
2
    case PILOT_KEY::KEY_UP:
146
1
    {
147
1
        useful_F::runLinuxCommand("echo -n $'\x1b\x5b\x44' > /mnt/ramdisk/cmd"); // do tylu
148
1
        // write_to_mkfifo("$'\x1b\x5b\x44'");
149
1
        break;
150
2
    }
151
2
    case PILOT_KEY::KEY_CHANNELUP:
152
1
    {
153
1
        //system("echo -n o > /mnt/ramdisk/cmd"); // do przodu
154
1
        useful_F_libs::write_to_mkfifo(my_data->server_settings->omxplayerFile, "o");
155
1
        break;
156
2
    }
157
2
    case PILOT_KEY::KEY_CHANNELDOWN:
158
1
    {
159
1
        //system("echo -n i > /mnt/ramdisk/cmd"); // do tylu
160
1
        useful_F_libs::write_to_mkfifo(my_data->server_settings->omxplayerFile, "i");
161
1
        break;
162
2
    }
163
2
    default:
164
1
        log_file_mutex.mutex_lock();
165
1
        log_file_cout << CRITICAL << "nieznany case w projector"<< std::endl;
166
1
        log_file_mutex.mutex_unlock();
167
1
        break;
168
12
    }
169
12
}
170
171
void c_irda_logic::movieLogic(PILOT_KEY X)
172
14
{
173
14
    switch (X)
174
14
    {
175
14
    case PILOT_KEY::KEY_EXIT:
176
1
    {
177
1
        my_data->mainLCD->set_print_song_state(0);
178
1
        my_data->mainLCD->set_lcd_STATE(2);
179
1
        who = PILOT_STATE::MPD; // koniec przegladania katalogow
180
1
        break;
181
1
    }
182
3
    case PILOT_KEY::KEY_VOLUMEUP:
183
3
    {
184
3
        my_data->main_tree->next(); // naspteny katalog
185
3
        break;
186
1
    }
187
5
    case PILOT_KEY::KEY_VOLUMEDOWN:
188
5
    {
189
5
        my_data->main_tree->previous(); //poprzedni katalog
190
5
        break;
191
1
    }
192
3
    case PILOT_KEY::KEY_OK:
193
3
    {
194
3
        // whodze w katalog lub odtwarzma plik
195
3
196
3
        if (my_data->main_tree->is_file() == false)
197
3
        {
198
1
            my_data->main_tree->enter_dir();
199
1
            my_data->main_tree->show_list();
200
1
        }
201
3
        else
202
3
        {
203
2
            std::cout << " URUCHAMIAM PLIK! " <<my_data->main_tree->show_list() <<std::endl;
204
2
205
2
            std::string command = "/home/pi/programowanie/iDom_server_OOP/script/PYTHON/iDom_movie.py ";
206
2
            command+=my_data->main_tree->show_list();
207
2
            useful_F::runLinuxCommand(command);
208
2
            std::cout << " WYSTARTOWALEM!!";
209
2
            my_data->mainLCD->set_lcd_STATE(-1);
210
2
            my_data->mainLCD->printString(true,0,0,"odtwarzam film");
211
2
            my_data->mainLCD->printString(false,0,1,my_data->main_tree->show_list());
212
2
            who = PILOT_STATE::PROJECTOR;
213
2
214
2
            log_file_mutex.mutex_lock();
215
2
            log_file_cout << INFO << "odtwarzam film "<< my_data->ptr_MPD_info->isPlay << std::endl;
216
2
            log_file_mutex.mutex_unlock();
217
2
218
2
            if (my_data->ptr_MPD_info->isPlay == true){
219
1
                iDomTOOLS::MPD_pause(); // projektor wlaczony wiec pauzuje radio
220
1
            }
221
2
            else{
222
1
                iDomTOOLS::turnOnSpeakers();
223
1
                puts("wlaczam glosnik do filmu");
224
1
            }
225
2
        }
226
3
        break;
227
1
    }
228
1
    case PILOT_KEY::KEY_UP:
229
1
    {
230
1
        my_data->main_tree->back_dir();
231
1
        break;
232
1
    }
233
1
    default:
234
1
        log_file_mutex.mutex_lock();
235
1
        log_file_cout << CRITICAL << "nieznany case w moveLogic"<< std::endl;
236
1
        log_file_mutex.mutex_unlock();
237
1
        break;
238
14
    }
239
14
240
14
    my_data->main_tree->show_list();
241
14
}
242
243
void c_irda_logic::menuLogic(PILOT_KEY X)
244
39
{
245
39
    switch (X)
246
39
    {
247
39
    case PILOT_KEY::KEY_EXIT:
248
1
    {
249
1
        my_data->mainLCD->set_print_song_state(0);
250
1
        my_data->mainLCD->set_lcd_STATE(2);
251
1
        who = PILOT_STATE::MPD; // koniec przegladania katalogow
252
1
        break;
253
1
    }
254
23
    case PILOT_KEY::KEY_VOLUMEUP:
255
23
    {
256
23
        my_data->main_MENU->next(); // naspteny katalog
257
23
        break;
258
1
    }
259
6
    case PILOT_KEY::KEY_VOLUMEDOWN:
260
6
    {
261
6
        my_data->main_MENU->previous(); //poprzedni katalog
262
6
        break;
263
1
    }
264
7
    case PILOT_KEY::KEY_OK:
265
7
    {
266
7
        // whodze w katalog lub odtwarzma plik
267
7
268
7
        if (my_data->main_MENU->is_file() == false)
269
7
        {
270
1
            my_data->main_MENU->enter_dir();
271
1
            my_data->main_MENU->show_list();
272
1
        }
273
7
        else
274
7
        {
275
6
            // menu start
276
6
            if (my_data->main_MENU->show_list() == "5.SLEEPer"){
277
2
                std::cout << " POBUDKA!!!!" << std::endl;
278
2
                who=PILOT_STATE::SLEEPER;
279
2
            }
280
6
            else if (my_data->main_MENU->show_list() == "2.TEMPERATURA"){
281
1
                std::cout << " temperatura !!!!" << std::endl;
282
1
                who=PILOT_STATE::MPD;
283
1
                _add(PILOT_KEY::KEY_SAT);
284
1
            }
285
4
            else if (my_data->main_MENU->show_list() == "4.PLIKI"){
286
3
                std::cout << " do filmow" << std::endl;
287
3
                who=PILOT_STATE::MPD;
288
3
                _add(PILOT_KEY::KEY_EPG);
289
3
                _add(PILOT_KEY::KEY_VOLUMEUP);
290
3
            }
291
6
        }
292
7
        break;
293
1
    }
294
1
    case PILOT_KEY::KEY_UP:
295
1
    {
296
1
        my_data->main_MENU->back_dir();
297
1
        break;
298
1
    }
299
1
    default:
300
1
        log_file_mutex.mutex_lock();
301
1
        log_file_cout << CRITICAL << "nieznany case w menuLogic"<< std::endl;
302
1
        log_file_mutex.mutex_unlock();
303
1
        break;
304
39
305
39
    }
306
39
    my_data->main_MENU->show_list();
307
39
}
308
309
void c_irda_logic::mainPilotHandler(PILOT_KEY X)
310
36
{
311
36
    switch (X){
312
36
313
36
    case PILOT_KEY::KEY_RADIO:
314
1
    {
315
1
        who = PILOT_STATE::PROJECTOR;
316
1
        _add(PILOT_KEY::DUMMY);
317
1
        break;
318
1
    }
319
1
320
1
    case PILOT_KEY::KEY_SUBTITLE:
321
1
    {
322
1
        my_data->mainLCD->set_lcd_STATE(10);
323
1
        my_data->mainLCD->printString(true,0,0,"GASZE LEDy");
324
1
        std::string temp_str="";
325
1
        temp_str.erase();
326
1
        temp_str += my_data->main_iDomTools->ledOFF();
327
1
        my_data->mainLCD->printString(false,0,1,temp_str);
328
1
        who=PILOT_STATE::MPD;
329
1
        break;
330
1
    }
331
1
332
9
    case PILOT_KEY::KEY_LANGUAGE:
333
9
    {
334
9
        my_data->mainLCD->set_lcd_STATE(10);
335
9
        my_data->mainLCD->printString(true,0,0,"ZAPALAM LEDy");
336
9
        std::string temp_str = my_data->ptr_pilot_led->colorLED[my_data->ptr_pilot_led->counter].getColorName();
337
9
        my_data->main_iDomTools->ledOn(my_data->ptr_pilot_led->colorLED[my_data->ptr_pilot_led->counter]);
338
9
339
9
        if (++my_data->ptr_pilot_led->counter > my_data->ptr_pilot_led->colorLED.size()-1 )
340
9
        {
341
1
            my_data->ptr_pilot_led->counter=0;
342
1
        }
343
9
344
9
        my_data->mainLCD->printString(false,0,1,temp_str);
345
9
        who = PILOT_STATE::MPD;
346
9
        break;
347
1
    }
348
1
349
1
    case PILOT_KEY::KEY_SAT:
350
1
    {
351
1
        my_data->mainLCD->set_lcd_STATE(10);
352
1
        my_data->mainLCD->printString(true,0,0,"SMOG: "+my_data->main_iDomTools->getSmog()+" mg/m^3");
353
1
        std::string temp_str = "I:";
354
1
        std::vector<std::string> temper = my_data->main_iDomTools->getTemperature();
355
1
        //temp_str += my_data_logic->main_iDomTools->getTemperatureString();// send_to_arduino(my_data_logic,"temperature:2;");
356
1
        temp_str += temper.at(0);
357
1
        temp_str += " O:"+ temper.at(1);
358
1
        my_data->mainLCD->printString(false,0,1,temp_str+" c");
359
1
        who = PILOT_STATE::MPD;
360
1
        break;
361
1
    }
362
1
363
3
    case PILOT_KEY::KEY_EPG:
364
3
        who = PILOT_STATE::MOVIE;
365
3
        my_data->main_tree->show_list(); //printuje pierwszy element
366
3
        my_data->mainLCD->set_print_song_state(100);
367
3
        break;
368
1
369
7
    case PILOT_KEY::KEY_MENU:
370
7
        who = PILOT_STATE::MENU;
371
7
        my_data->main_MENU->show_list();
372
7
        my_data->mainLCD->set_print_song_state(100);
373
7
        break;
374
1
    case PILOT_KEY::KEY_FAVORITES:
375
1
        my_data->main_iDomTools->turnOnOffPrinter();
376
1
        break;
377
2
    case PILOT_KEY::KEY_TEXT:
378
2
        my_data->main_iDomTools->turnOnOff433MHzSwitch("listwa");
379
2
        break;
380
1
    case PILOT_KEY::KEY_REFRESH:
381
1
        my_data->main_iDomTools->startKodi_Thread();
382
1
        break;
383
10
    default:
384
10
        irdaMPD(X);
385
36
    }
386
36
}
387
388
c_irda_logic::c_irda_logic(thread_data *my_data):my_data(my_data)
389
12
{
390
12
    // my_data = my_data;
391
12
    who = PILOT_STATE::MPD;
392
12
}
393
394
void c_irda_logic::_add(PILOT_KEY X)
395
111
{
396
111
    switch (who){
397
111
    case PILOT_STATE::MPD:
398
35
        mainPilotHandler(X);
399
35
        break;
400
35
    case PILOT_STATE::SLEEPER:
401
10
        sleeperLogic(X);
402
10
        break;
403
35
    case PILOT_STATE::PROJECTOR:
404
12
        projectorLogic(X);
405
12
        break;
406
35
    case PILOT_STATE::MOVIE:
407
14
        movieLogic(X);
408
14
        break;
409
39
    case PILOT_STATE::MENU:
410
39
        menuLogic(X);
411
39
        break;
412
35
    default:
413
1
        log_file_mutex.mutex_lock();
414
1
        log_file_cout << CRITICAL << "nieznany pilotState"<< std::endl;
415
1
        log_file_mutex.mutex_unlock();
416
1
        break;
417
111
    }
418
111
}
419
420
//PILOT_KEY c_irda_logic::_get( )
421
//{
422
//    PILOT_KEY temp = PILOT_KEY::DUMMY;
423
//    if (irda_queue.empty() == false){
424
//        temp = irda_queue.front();
425
//        irda_queue.pop();
426
//    }
427
//    return temp;
428
//}
429
430
//int c_irda_logic::_size() const
431
//{
432
//    return irda_queue.size();
433
//}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_event_BT.cpp
Line
Count
Source
1
#include "../command_event.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_event_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_event_Class_fixture()
8
6
    {
9
6
10
6
    }
11
12
protected:
13
    std::unique_ptr<command_event> test_command_event;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
17
6
    {
18
6
        iDomTOOLS_ClassTest::SetUp();
19
6
        test_command_event = std::make_unique <command_event> ("event");
20
6
    }
21
22
    void TearDown() final
23
6
    {
24
6
        iDomTOOLS_ClassTest::TearDown();
25
6
    }
26
};
27
28
TEST_F(command_event_Class_fixture, eventList)
29
1
{
30
1
    test_v.push_back("event");
31
1
    auto ret = test_command_event->execute(test_v,&test_my_data);
32
1
    EXPECT_THAT(ret, ::testing::HasSubstr("pilot"));
33
1
}
34
35
TEST_F(command_event_Class_fixture, eventPilot)
36
1
{
37
1
    test_v.push_back("event");
38
1
    test_v.push_back("pilot");
39
1
    auto ret = test_command_event->execute(test_v,&test_my_data);
40
1
    EXPECT_THAT(ret, ::testing::HasSubstr("pilot"));
41
1
}
42
43
TEST_F(command_event_Class_fixture, clearEventPilot)
44
1
{
45
1
    test_my_data.myEventHandler.run("pilot")->addEvent("pilot test");
46
1
    EXPECT_EQ(test_my_data.myEventHandler.run("pilot")->howManyEvent(),1);
47
1
    test_v.push_back("event");
48
1
    test_v.push_back("pilot");
49
1
    test_v.push_back("clear");
50
1
    test_command_event->execute(test_v,&test_my_data);
51
1
    EXPECT_EQ(test_my_data.myEventHandler.run("pilot")->howManyEvent(),0);
52
1
}
53
54
TEST_F(command_event_Class_fixture, clearsSomeEventPilot)
55
1
{
56
11
    for(int i = 0; i<10; ++i){
57
10
    test_my_data.myEventHandler.run("pilot")->addEvent("pilot test");
58
10
    }
59
1
    EXPECT_EQ(test_my_data.myEventHandler.run("pilot")->howManyEvent(),10);
60
1
    test_v.push_back("event");
61
1
    test_v.push_back("pilot");
62
1
    test_v.push_back("clear");
63
1
    test_v.push_back("3");
64
1
    test_v.push_back("6");
65
1
    test_command_event->execute(test_v,&test_my_data);
66
1
    EXPECT_EQ(test_my_data.myEventHandler.run("pilot")->howManyEvent(),7);
67
1
}
68
69
TEST_F(command_event_Class_fixture, intensityEventPilot)
70
1
{
71
1
    test_my_data.myEventHandler.run("pilot")->addEvent("pilot test");
72
1
    EXPECT_EQ(test_my_data.myEventHandler.run("pilot")->howManyEvent(),1);
73
1
    test_v.push_back("event");
74
1
    test_v.push_back("pilot");
75
1
    test_v.push_back("intensity");
76
1
    auto ret = test_command_event->execute(test_v,&test_my_data);
77
1
    EXPECT_STREQ(ret.c_str(),"event pilot 1 intensity per last minute!");
78
1
    EXPECT_EQ(test_my_data.myEventHandler.run("pilot")->howManyEvent(),1);
79
1
}
80
81
TEST_F(command_event_Class_fixture, wrongParamiter)
82
1
{
83
1
    test_v.push_back("event");
84
1
    test_v.push_back("pilot");
85
1
    test_v.push_back("clear");
86
1
    test_v.push_back("3");
87
1
    test_v.push_back("6");
88
1
    test_v.push_back("clear");
89
1
    test_v.push_back("3");
90
1
    test_v.push_back("6");
91
1
    test_v.push_back("clear");
92
1
    test_v.push_back("3");
93
1
    test_v.push_back("6");
94
1
    auto ret = test_command_event->execute(test_v,&test_my_data);
95
1
    EXPECT_THAT(ret,::testing::HasSubstr("event"));
96
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/c_irda_logic/test/c_irda_logic_BT.cpp
Line
Count
Source (jump to first uncovered line)
1
#include <gtest/gtest.h>
2
#include "../../iDom_server_OOP.h"
3
#include "test_data.h"
4
#include "../../../iDom_server_OOP/src/iDomTools/test/iDomTools_fixture.h"
5
#include "../c_irda_logic.h"
6
7
8
class c_irda_logic_fixture : public iDomTOOLS_ClassTest
9
{
10
public:
11
    std::unique_ptr<c_irda_logic> test_irda;
12
    menu_tree* test_menuTree;
13
    files_tree* test_filesTree;
14
    std::string test_omxplayerFile = "../config/cmd_test";
15
    void SetUp()
16
12
    {
17
12
        iDomTOOLS_ClassTest::SetUp();
18
12
        test_irda = std::make_unique<c_irda_logic>(&test_my_data);
19
12
        test_menuTree = new menu_tree("../config/MENU/", test_my_data.mainLCD);
20
12
        test_my_data.main_MENU = test_menuTree;
21
12
22
12
        test_filesTree = new files_tree("../config/MOVIE/", test_my_data.mainLCD);
23
12
        test_my_data.main_tree = test_filesTree;
24
12
25
12
        test_my_data.server_settings->omxplayerFile =  test_omxplayerFile;
26
12
27
12
        std::cout << "c_irda_logic_fixture SetUp()"<<std::endl;
28
12
    }
29
30
    void TearDown()
31
12
    {
32
12
        delete test_menuTree;
33
12
        delete test_filesTree;
34
12
        iDomTOOLS_ClassTest::TearDown();
35
12
        std::cout << "c_irda_logic_fixture TearDown()"<<std::endl;
36
12
    }
37
};
38
39
TEST_F(c_irda_logic_fixture, kodi)
40
1
{
41
1
    std::array<Thread_array_struc,iDomConst::MAX_CONNECTION >test_ThreadArrayStruc;
42
1
43
11
    for (int i = 0 ; i < iDomConst::MAX_CONNECTION; i++)
44
10
        test_ThreadArrayStruc.at(i).thread_socket = i+1;
45
1
    test_ThreadArrayStruc.at(3).thread_socket = 0;
46
1
    test_my_data.main_THREAD_arr = &test_ThreadArrayStruc;
47
1
48
1
    test_my_data.main_iDomTools->unlockHome();
49
1
    test_my_data.main_iDomStatus->setObjectState("music",STATE::PAUSE);
50
1
    test_my_data.main_iDomStatus->setObjectState("speakers",STATE::OFF);
51
1
    test_irda->_add(PILOT_KEY::KEY_REFRESH);
52
1
    sleep(1);
53
1
}
54
55
TEST_F(c_irda_logic_fixture, turnOnOffListwa)
56
1
{
57
1
    test_my_data.main_iDomTools->unlockHome();
58
1
    test_my_data.main_iDomStatus->setObjectState("listwa",STATE::OFF);
59
1
60
1
    EXPECT_EQ(test_my_data.main_REC->getEqPointer("listwa")->getState(), STATE::UNDEFINE);
61
1
    test_irda->_add(PILOT_KEY::KEY_TEXT);
62
1
63
3
    EXPECT_EQ(test_my_data.main_REC->getEqPointer("listwa")->getState(),
64
3
              STATE::ON) << "wrong state: "
65
3
                         << stateToString(test_my_data.main_REC->getEqPointer("listwa")->getState());
66
1
    test_irda->_add(PILOT_KEY::KEY_TEXT);
67
1
68
3
    EXPECT_EQ(test_my_data.main_REC->getEqPointer("listwa")->getState(),
69
3
              STATE::OFF) << "wrong state: "
70
3
                          << stateToString(test_my_data.main_REC->getEqPointer("listwa")->getState());
71
1
}
72
73
TEST_F(c_irda_logic_fixture, turnOnOffPrinter)
74
1
{
75
1
    setReturnPinState(0);
76
1
    test_my_data.main_iDomTools->unlockHome();
77
1
    test_my_data.main_iDomStatus->setObjectState("printer", STATE::OFF);
78
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("printer"),
79
1
              STATE::OFF);
80
1
81
1
    test_irda->mainPilotHandler(PILOT_KEY::KEY_FAVORITES);
82
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("printer"),
83
1
              STATE::ON);
84
1
    std::cout <<"event: " << test_my_data.myEventHandler.run("230V")->getEvent() <<std::endl;
85
1
}
86
87
TEST_F(c_irda_logic_fixture, irdaMPD)
88
1
{
89
1
    blockQueue test_Q;
90
1
    test_Q._clearAll();
91
1
92
1
    test_irda->_add(PILOT_KEY::KEY_POWER);
93
1
    EXPECT_EQ(test_Q._get(), MPD_COMMAND::STOP);
94
1
95
1
    test_irda->_add(PILOT_KEY::KEY_TV);
96
1
    EXPECT_EQ(test_Q._get(), MPD_COMMAND::PLAY);
97
1
98
1
    test_irda->_add(PILOT_KEY::KEY_VOLUMEDOWN);
99
1
    EXPECT_EQ(test_Q._get(), MPD_COMMAND::VOLDOWN);
100
1
101
1
    test_irda->_add(PILOT_KEY::KEY_VOLUMEUP);
102
1
    EXPECT_EQ(test_Q._get(), MPD_COMMAND::VOLUP);
103
1
104
1
    test_irda->_add(PILOT_KEY::KEY_AUDIO);
105
1
    EXPECT_EQ(test_Q._get(), MPD_COMMAND::PAUSE);
106
1
107
1
    test_irda->_add(PILOT_KEY::KEY_UP);
108
1
    EXPECT_EQ(test_Q._get(), MPD_COMMAND::NEXT);
109
1
110
1
    test_irda->_add(PILOT_KEY::KEY_DOWN);
111
1
    EXPECT_EQ(test_Q._get(), MPD_COMMAND::PREV);
112
1
113
1
    test_irda->_add(PILOT_KEY::KEY_2); //default
114
1
    EXPECT_EQ(test_Q._size(), 0);
115
1
}
116
TEST_F(c_irda_logic_fixture, sleeper_Logic_EXIT)
117
1
{
118
1
    test_my_data.sleeper = 0;
119
1
    EXPECT_EQ(test_my_data.sleeper, 0);
120
1
    test_irda->_add(PILOT_KEY::KEY_MENU);
121
4
    do {
122
4
        test_irda->_add(PILOT_KEY::KEY_VOLUMEUP);
123
4
    } while(TEST_DATA::LCD_print != "5.SLEEPer");
124
5
    do {
125
5
        test_irda->_add(PILOT_KEY::KEY_VOLUMEDOWN);
126
5
    } while(TEST_DATA::LCD_print != "5.SLEEPer");
127
1
    test_irda->_add(PILOT_KEY::KEY_OK);
128
1
    test_irda->_add(PILOT_KEY::KEY_UP);
129
1
    EXPECT_EQ(test_my_data.sleeper, 1);
130
1
    test_irda->_add(PILOT_KEY::KEY_UP);
131
1
    EXPECT_EQ(test_my_data.sleeper, 2);
132
1
    test_irda->_add(PILOT_KEY::KEY_EXIT);
133
1
    EXPECT_EQ(test_my_data.sleeper, 0);
134
1
}
135
136
TEST_F(c_irda_logic_fixture, sleeper_Logic_OK)
137
1
{
138
1
    std::cout << test_my_data.main_REC->listAllName() << std::endl;
139
1
140
1
    std::array<Thread_array_struc,iDomConst::MAX_CONNECTION> test_ThreadArrayStruc;
141
1
142
11
    for (int i = 0 ; i < iDomConst::MAX_CONNECTION; i++)
143
10
        test_ThreadArrayStruc.at(i).thread_socket = i+1;
144
1
    test_ThreadArrayStruc.at(3).thread_socket = 0;
145
1
    test_my_data.main_THREAD_arr = &test_ThreadArrayStruc;
146
1
    test_my_data.sleeper = 0;
147
1
    EXPECT_EQ(test_my_data.sleeper, 0);
148
1
    test_irda->_add(PILOT_KEY::KEY_MENU);
149
4
    do {
150
4
        test_irda->_add(PILOT_KEY::KEY_VOLUMEUP);
151
4
    } while(TEST_DATA::LCD_print != "5.SLEEPer");
152
1
    test_irda->_add(PILOT_KEY::KEY_OK);
153
1
    test_irda->_add(PILOT_KEY::KEY_UP);
154
1
    EXPECT_EQ(test_my_data.sleeper, 1);
155
1
    test_irda->_add(PILOT_KEY::KEY_UP);
156
1
    EXPECT_EQ(test_my_data.sleeper, 2);
157
1
    test_irda->_add(PILOT_KEY::KEY_CHANNELUP);
158
1
    EXPECT_EQ(test_my_data.sleeper, 12);
159
1
    test_irda->_add(PILOT_KEY::KEY_CHANNELDOWN);
160
1
    EXPECT_EQ(test_my_data.sleeper, 2);
161
1
    test_irda->_add(PILOT_KEY::KEY_DOWN);
162
1
    EXPECT_EQ(test_my_data.sleeper, 1);
163
1
    test_irda->_add(PILOT_KEY::KEY_OK);
164
1
    sleep(2);
165
1
    EXPECT_EQ(test_my_data.sleeper, 0);
166
1
    test_irda->_add(PILOT_KEY::KEY_EXIT);
167
1
    EXPECT_EQ(test_my_data.sleeper, 0);\
168
1
169
1
    //////////////default
170
1
    test_irda->who = PILOT_STATE::SLEEPER;
171
1
    test_irda->_add(PILOT_KEY::KEY_0); //default
172
1
}
173
174
TEST_F(c_irda_logic_fixture, LED_ON_OFF)
175
1
{
176
1
    EXPECT_EQ( test_my_data.myEventHandler.run("LED")->getLast1minNumberEvent(),0);
177
10
    for (int i = 1 ; i < test_my_data.ptr_pilot_led->colorLED.size()+2; ++i)
178
9
    {
179
9
        test_irda->_add(PILOT_KEY::KEY_LANGUAGE);
180
9
        EXPECT_EQ( test_my_data.myEventHandler.run("LED")->getLast1minNumberEvent(),i);
181
9
        EXPECT_THAT(test_my_data.myEventHandler.run("LED")->getEvent(),
182
9
                    testing::HasSubstr("LED can not start due to home state: UNDEFINE"));
183
9
    }
184
1
    test_irda->_add(PILOT_KEY::KEY_SUBTITLE);
185
1
}
186
TEST_F(c_irda_logic_fixture, temp_smogINFO)
187
1
{
188
1
    TEST_DATA::return_httpPost = "ok.\n";
189
1
    TEST_DATA::return_send_to_arduino = "12:12";
190
1
    test_irda->_add(PILOT_KEY::KEY_MENU);
191
1
    do {
192
1
        test_irda->_add(PILOT_KEY::KEY_VOLUMEUP);
193
1
    } while(TEST_DATA::LCD_print != "2.TEMPERATURA");
194
1
195
1
    test_irda->_add(PILOT_KEY::KEY_VOLUMEUP);
196
1
    test_irda->_add(PILOT_KEY::KEY_VOLUMEDOWN);
197
1
    test_irda->_add(PILOT_KEY::KEY_OK);
198
1
    EXPECT_THAT(TEST_DATA::LCD_print, testing::HasSubstr("TEMPERATURA"));
199
1
}
200
201
TEST_F(c_irda_logic_fixture, menu_enter_dir)
202
1
{
203
1
    test_irda->_add(PILOT_KEY::KEY_MENU);
204
1
    test_irda->_add(PILOT_KEY::KEY_OK);
205
1
206
1
    EXPECT_EQ(test_irda->who, PILOT_STATE::MENU);
207
1
    test_irda->_add(PILOT_KEY::KEY_UP);
208
1
    test_irda->_add(PILOT_KEY::KEY_0); //default
209
1
    test_irda->_add(PILOT_KEY::KEY_EXIT);
210
1
    EXPECT_EQ(test_irda->who, PILOT_STATE::MPD);
211
1
}
212
TEST_F(c_irda_logic_fixture, menu_files)
213
1
{
214
1
    blockQueue  test_q;
215
1
    test_q._clearAll();
216
1
    test_my_data.idom_all_state.houseState = STATE::UNLOCK;
217
1
    int timeout = 10;
218
1
    test_irda->_add(PILOT_KEY::KEY_MENU);
219
3
    do {
220
3
        if (--timeout == 0)
221
3
            FAIL()<<"cannot find";
222
3
        test_irda->_add(PILOT_KEY::KEY_VOLUMEUP);
223
3
    } while(TEST_DATA::LCD_print != "4.PLIKI");
224
1
    test_irda->_add(PILOT_KEY::KEY_OK);
225
1
    EXPECT_EQ(test_irda->who, PILOT_STATE::MOVIE);
226
1
    timeout = 10;
227
2
    do {
228
2
        if (--timeout == 0)
229
2
            FAIL()<<"cannot find";
230
2
        test_irda->_add(PILOT_KEY::KEY_VOLUMEDOWN);
231
2
    } while(TEST_DATA::LCD_print != "GAME_OF_THRONES/");
232
1
    test_irda->_add(PILOT_KEY::KEY_OK);
233
1
    test_irda->_add(PILOT_KEY::KEY_UP);
234
1
    EXPECT_STREQ(TEST_DATA::LCD_print.c_str(),"GAME_OF_THRONES/");
235
1
    test_irda->_add(PILOT_KEY::KEY_EXIT);
236
1
    EXPECT_EQ(test_irda->who, PILOT_STATE::MPD);
237
1
    ///////////////// play - no MPD
238
1
239
1
    test_my_data.ptr_MPD_info->isPlay  = false;
240
1
    test_irda->_add(PILOT_KEY::KEY_MENU);
241
1
    timeout = 10;
242
5
    do {
243
5
        if (--timeout == 0)
244
5
            FAIL()<<"cannot find";
245
5
        test_irda->_add(PILOT_KEY::KEY_VOLUMEUP);
246
5
    } while(TEST_DATA::LCD_print != "4.PLIKI");
247
1
    test_irda->_add(PILOT_KEY::KEY_OK);
248
1
    EXPECT_EQ(test_irda->who, PILOT_STATE::MOVIE);
249
1
    timeout = 10;
250
2
    do {
251
2
        if (--timeout == 0)
252
2
            break;
253
2
        test_irda->_add(PILOT_KEY::KEY_VOLUMEDOWN);
254
2
    } while(TEST_DATA::LCD_print != "s01e02");
255
1
    test_irda->_add(PILOT_KEY::KEY_0); //default
256
1
    test_irda->_add(PILOT_KEY::KEY_OK);
257
1
    EXPECT_EQ(test_irda->who, PILOT_STATE::PROJECTOR);
258
1
    test_irda->_add(PILOT_KEY::KEY_EXIT);
259
1
    EXPECT_EQ(test_irda->who, PILOT_STATE::MPD);
260
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("speakers"),STATE::OFF);
261
1
    ///////////////// play -  MPD
262
1
    test_my_data.ptr_MPD_info->isPlay  = true;
263
1
    EXPECT_TRUE(test_my_data.ptr_MPD_info->isPlay);
264
1
    test_irda->_add(PILOT_KEY::KEY_MENU);
265
1
    timeout = 10;
266
5
    do {
267
5
        if (--timeout == 0)
268
5
            FAIL()<<"cannot find";
269
5
        test_irda->_add(PILOT_KEY::KEY_VOLUMEUP);
270
5
    } while(TEST_DATA::LCD_print != "4.PLIKI");
271
1
    test_irda->_add(PILOT_KEY::KEY_OK);
272
1
    EXPECT_EQ(test_irda->who, PILOT_STATE::MOVIE);
273
1
    timeout = 10;
274
1
    do {
275
1
        if (--timeout == 0)
276
1
            FAIL()<<"cannot find";
277
1
        test_irda->_add(PILOT_KEY::KEY_VOLUMEDOWN);
278
1
    } while(TEST_DATA::LCD_print != "s01e02");
279
1
    test_irda->_add(PILOT_KEY::KEY_OK);
280
1
    EXPECT_EQ(test_irda->who, PILOT_STATE::PROJECTOR);
281
1
282
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::PAUSE);
283
1
}
284
285
TEST_F(c_irda_logic_fixture, dummy_KEY_RADIO_and_add )
286
1
{
287
1
    test_irda->_add(PILOT_KEY::KEY_RADIO);
288
1
    EXPECT_EQ(test_irda->who, PILOT_STATE::PROJECTOR);
289
1
290
1
    test_irda->who = PILOT_STATE::LED; //not set
291
1
    test_irda->_add(PILOT_KEY::KEY_RADIO);
292
1
}
293
294
TEST_F(c_irda_logic_fixture, projektor)
295
1
{
296
1
    std::string retString;
297
1
    test_irda->who = PILOT_STATE::PROJECTOR;
298
1
    test_irda->_add(PILOT_KEY::KEY_VOLUMEUP);
299
1
    retString = useful_F_libs::read_from_mkfifo(test_omxplayerFile.c_str());
300
1
    std::cout << "DUPA: " << retString.size() << std::endl;
301
1
   // EXPECT_EQ(retString,"+");
302
1
303
1
    test_irda->_add(PILOT_KEY::KEY_VOLUMEDOWN);
304
1
    retString = useful_F_libs::read_from_mkfifo(test_omxplayerFile.c_str());
305
1
    std::cout << "DUPA: " << retString.size() << std::endl;
306
1
   // EXPECT_EQ(retString,"+");
307
1
308
1
    test_irda->_add(PILOT_KEY::KEY_OK);
309
1
    retString = useful_F_libs::read_from_mkfifo(test_omxplayerFile.c_str());
310
1
    std::cout << "DUPA: " << retString.size() << std::endl;
311
1
   // EXPECT_EQ(retString,"-");
312
1
313
1
    test_irda->_add(PILOT_KEY::KEY_POWER);
314
1
    retString = useful_F_libs::read_from_mkfifo(test_omxplayerFile.c_str());
315
1
    std::cout << "DUPA: " << retString.size() << std::endl;
316
1
   // EXPECT_EQ(retString,"q");
317
1
318
1
    test_irda->_add(PILOT_KEY::KEY_DOWN);
319
1
    retString = useful_F_libs::read_from_mkfifo(test_omxplayerFile.c_str());
320
1
    std::cout << "DUPA: " << retString.size() << std::endl;
321
1
   // EXPECT_EQ(retString,"+");
322
1
323
1
    test_irda->_add(PILOT_KEY::KEY_UP);
324
1
    retString = useful_F_libs::read_from_mkfifo(test_omxplayerFile.c_str());
325
1
    std::cout << "DUPA: " << retString.size() << std::endl;
326
1
   // EXPECT_EQ(retString,"+");
327
1
328
1
    test_irda->_add(PILOT_KEY::KEY_CHANNELUP);
329
1
    retString = useful_F_libs::read_from_mkfifo(test_omxplayerFile.c_str());
330
1
    std::cout << "DUPA: " << retString.size() << std::endl;
331
1
   // EXPECT_EQ(retString,"o");
332
1
333
1
    test_irda->_add(PILOT_KEY::KEY_CHANNELDOWN);
334
1
    retString = useful_F_libs::read_from_mkfifo(test_omxplayerFile.c_str());
335
1
    std::cout << "DUPA: " << retString.size() << std::endl;
336
1
   // EXPECT_EQ(retString,"i");
337
1
338
1
    test_my_data.ptr_MPD_info->isPlay = true;
339
1
    test_irda->_add(PILOT_KEY::KEY_EXIT);
340
1
    retString = useful_F_libs::read_from_mkfifo(test_omxplayerFile.c_str());
341
1
    std::cout << "DUPA: " << retString.size() << std::endl;
342
1
    EXPECT_EQ(test_irda->who, PILOT_STATE::MPD);
343
1
344
1
    test_my_data.ptr_MPD_info->isPlay = false;
345
1
    test_irda->_add(PILOT_KEY::KEY_EXIT);
346
1
    retString = useful_F_libs::read_from_mkfifo(test_omxplayerFile.c_str());
347
1
    std::cout << "DUPA: " << retString.size() << std::endl;
348
1
    EXPECT_EQ(test_irda->who, PILOT_STATE::MPD);
349
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("speakers"),STATE::OFF);
350
351
    //// dummy
352
    test_irda->who = PILOT_STATE::PROJECTOR;
353
    test_irda->_add(PILOT_KEY::KEY_0);
354
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_exit_BT.cpp
Line
Count
Source
1
#include "../commandexit.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_exit_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_exit_Class_fixture()
8
1
    {
9
1
10
1
    }
11
12
protected:
13
    std::unique_ptr<commandEXIT> test_command_exit;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
17
1
    {
18
1
        iDomTOOLS_ClassTest::SetUp();
19
1
        test_command_exit = std::make_unique <commandEXIT> ("exit");
20
1
    }
21
22
    void TearDown() final
23
1
    {
24
1
        iDomTOOLS_ClassTest::TearDown();
25
1
    }
26
};
27
28
TEST_F(command_exit_Class_fixture, main)
29
1
{
30
1
    test_v.push_back("exit");
31
1
    auto ret = test_command_exit->execute(test_v,&test_my_data);
32
1
    EXPECT_STREQ(ret.c_str(),"\nEND.\n");
33
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/command.cpp
Line
Count
Source
1
#include "command.h"
2
3
command::command(const std::string &commandName ) : commandName(commandName)
4
266
{
5
266
   // std::cout << "konstruktor command"<<std::endl;
6
266
}
7
8
command::~command()
9
266
{
10
266
  // puts("command::~command()");
11
266
}
12
13
std::string command::getCommandName()
14
156
{
15
156
    return commandName;
16
156
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_hello_BT.cpp
Line
Count
Source
1
#include "../command_hello.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_hello_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_hello_Class_fixture()
8
1
    {
9
1
10
1
    }
11
12
protected:
13
    std::unique_ptr<command_hello> test_command_hello;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
17
1
    {
18
1
        iDomTOOLS_ClassTest::SetUp();
19
1
        test_command_hello = std::make_unique <command_hello> ("hello");
20
1
    }
21
22
    void TearDown() final
23
1
    {
24
1
        iDomTOOLS_ClassTest::TearDown();
25
1
    }
26
};
27
28
TEST_F(command_hello_Class_fixture, main)
29
1
{
30
1
    test_v.push_back("hello");
31
1
    auto ret = test_command_hello->execute(test_v,&test_my_data);
32
1
    EXPECT_STREQ(ret.c_str(),"\nHI You User!\n");
33
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/libs/useful/useful.h
Line
Count
Source
1
#ifndef Iusefull_H
2
#define Iusefull_H
3
4
#include <iostream>
5
#include <string>
6
#include <vector>
7
#include <ostream>
8
#include <chrono>
9
#include <sstream>
10
#include <stdio.h>
11
#include <stdlib.h>
12
#include <iomanip>
13
#ifndef ANDROID
14
#include "json.hpp"
15
#endif
16
17
std::vector<std::string> split_string(const std::string& s, char separator );
18
19
class useful_F_libs {
20
public:
21
    static  void write_to_mkfifo(const std::string& path, const std::string &msg);
22
    static  std::string read_from_mkfifo(const std::string &path);
23
    static size_t  WriteCallback(void *contents, size_t size, size_t nmemb, void *userp);
24
    static std::string find_tag (const std::string &temp);
25
    //////////////////// HTTP req //////////////////////////
26
    static std::string httpPost(const std::string &url, int timeoutSeconds);
27
    static std::string httpPost(const std::string &url);
28
    static void downloadFile(const std::string &url, const std::string &path, int timeoutSeconds);
29
    static std::string replaceAll(std::string str, const std::string& from, const std::string& to);
30
    static std::string removeHtmlTag(std::string &data);
31
    /////////////////////  JSON ////////////////////////////
32
33
#ifndef ANDROID
34
    static nlohmann::json getJson(const std::string &url);
35
#endif
36
};
37
namespace std
38
{
39
40
#ifdef ANDROID
41
template <typename T>
42
int stoi(T s){
43
    return atoi(s.c_str());
44
}
45
#endif
46
47
template <typename T>
48
std::string to_string(T value)
49
{
50
    std::ostringstream os;
51
    os << value;
52
    return os.str();
53
}
54
} // namespace std
55
56
template <typename T>
57
std::string to_string_with_precision(const T a_value, const int n = 4)
58
{
59
    std::ostringstream out;
60
    out << std::setprecision(n) << a_value;
61
    return out.str();
62
}
63
64
struct Clock{
65
private:
66
    std::time_t m_time;
67
#ifdef BT_TEST
68
    static unsigned int m_BT_H;
69
    static unsigned int m_BT_M;
70
#endif
71
public:
72
    unsigned int m_h = 0;
73
    unsigned int m_min = 0;
74
    Clock () {}
75
    Clock(std::string t){
76
        std::vector<std::string> vt = split_string(t,':');
77
        int h = std::stoi(vt.at(0));
78
        int m = std::stoi(vt.at(1));
79
        set(static_cast <unsigned int>(h),static_cast <unsigned int>(m));
80
    }
81
82
    Clock(unsigned int h, unsigned int m) {
83
        set(h,m);
84
    }
85
    /////////////////////////////////////////////////////////////////////////////////////
86
    void set(unsigned int h, unsigned int m){
87
        if (h<24 && m <60){
88
            this->m_h = h;
89
            this->m_min = m;
90
        }
91
        else {
92
            throw 0;
93
        }
94
    }
95
96
    /////////////////////////////////////////////////////////////////////////////////////
97
    const std::string getString(){
98
        std::stringstream ret;
99
        if (m_h < 10) {
100
            ret << "0";
101
        }
102
        ret << m_h;
103
        ret << ":";
104
        if (m_min < 10) {
105
            ret << "0";
106
        }
107
        ret << m_min;
108
        return ret.str();
109
    }
110
    /////////////////////////////////////////////////////////////////////////////////////
111
    bool operator == (const Clock & c){
112
        if ((this->m_h == c.m_h) && (this->m_min == c.m_min)){
113
            return true;
114
        }
115
        else{
116
            return false;
117
        }
118
    }
119
    /////////////////////////////////////////////////////////////////////////////////////
120
    bool operator != (const Clock & c){
121
        if ((this->m_h != c.m_h) || (this->m_min != c.m_min)){
122
            return true;
123
        }
124
        else{
125
            return false;
126
        }
127
    }
128
    /////////////////////////////////////////////////////////////////////////////////////
129
    friend std::ostream & operator<< (std::ostream &w ,  Clock &c) {
130
        return w << c.getString();
131
    }
132
    /////////////////////////////////////////////////////////////////////////////////////
133
    bool operator < (const Clock& c){
134
        if (this->m_h < c.m_h){
135
            return true;
136
        }
137
        else{
138
            if (this->m_h == c.m_h && this->m_min < c.m_min){
139
                return true;
140
            }
141
        }
142
        return false;
143
    }
144
    /////////////////////////////////////////////////////////////////////////////////////
145
    bool operator > (const Clock& c){
146
        if (this->m_h > c.m_h){
147
            return true;
148
        }
149
        else{
150
            if (this->m_h == c.m_h && this->m_min > c.m_min){
151
                return true;
152
            }
153
        }
154
        return false;
155
    }
156
    /////////////////////////////////////////////////////////////////////////////////////
157
    bool operator >= (const Clock& c){
158
        if (this->m_h > c.m_h){
159
            return true;
160
        }
161
        else if (this->m_h == c.m_h){
162
163
            if (this->m_min >= c.m_min){
164
                return true;
165
            }
166
        }
167
        return false;
168
    }
169
    /////////////////////////////////////////////////////////////////////////////////////
170
    bool operator <= (const Clock& c){
171
        if (this->m_h < c.m_h){
172
            return true;
173
        }
174
        else if (this->m_h == c.m_h){
175
176
            if (this->m_min <= c.m_min){
177
                return true;
178
            }
179
        }
180
        return false;
181
    }
182
    /////////////////////////////////////////////////////////////////////////////////////
183
    Clock  operator + (const Clock& c){
184
        unsigned int minutes, hours;
185
        minutes = m_min+ c.m_min;
186
        hours = m_h + c.m_h;
187
        if (minutes >59){
188
            minutes =  minutes % 60;
189
            hours+=1;
190
        }
191
        if (hours >= 24){
192
            hours-=24;
193
        }
194
        return  Clock(hours, minutes);
195
196
    }
197
    /////////////////////////////////////////////////////////////////////////////////////
198
    Clock&  operator += (const Clock& c){
199
        unsigned int minutes, hours;
200
        minutes = m_min+ c.m_min;
201
        hours = m_h + c.m_h;
202
        if (minutes >59){
203
            minutes =  minutes % 60;
204
            hours+=1;
205
        }
206
        if (hours >= 24){
207
            hours-=24;
208
        }
209
        this->m_h = hours;
210
        this->m_min = minutes;
211
        return *this;
212
213
    }
214
    /////////////////////////////////////////////////////////////////////////////////////
215
216
    unsigned int toSeconds(){
217
        return toSeconds(Clock(this->m_h, this->m_min) );
218
    }
219
    /////////////////////////////////////////////////////////////////////////////////////
220
221
    static unsigned int toSeconds(Clock t){
222
        return ((t.m_h*60) + t.m_min)*60;
223
    }
224
    /////////////////////////////////////////////////////////////////////////////////////
225
226
    static Clock fromSeconds(unsigned int sec){
227
        unsigned int h = sec/3600;
228
        unsigned int min = sec%3600;
229
        min = min/60;
230
        return Clock(h,min);
231
    }
232
    /////////////////////////////////////////////////////////////////////////////////////
233
234
    static Clock periodOfTime(Clock start, Clock end)
235
    {
236
        if (end >= start){
237
            return Clock::fromSeconds(end.toSeconds() - start.toSeconds()  );
238
        }
239
        else{
240
            return Clock::fromSeconds(end.toSeconds() + ( Clock::toSeconds(Clock(23,59))+ 60 - start.toSeconds() ) );
241
        }
242
        //return diff;
243
    }
244
    ////////////////////////////////////////////////////////////////////////////////////
245
    static unsigned int getUnixTime()
246
4
    {
247
4
        return static_cast<unsigned int> (std::time(nullptr));
248
4
    }
249
    /////////////////////////////////////////////////////////////////////////////////////
250
#ifdef BT_TEST
251
    static void setTime_forBT_usage(int h, int m)
252
    {
253
        m_BT_H = h;
254
        m_BT_M = m;
255
    }
256
#endif
257
    /////////////////////////////////////////////////////////////////////////////////////
258
    static Clock getTime()
259
    {
260
#ifdef BT_TEST
261
        return Clock(m_BT_H,m_BT_M);
262
#else
263
        time_t now = time(0);
264
        tm *ltm = localtime(&now);
265
        return Clock( static_cast <unsigned int>(ltm->tm_hour),static_cast <unsigned int>(ltm->tm_min) );
266
#endif
267
    }
268
    /////////////////////////////////////////////////////////////////////////////////////
269
    void stopwatchStart()
270
    {
271
        m_time = std::time(nullptr);
272
    }
273
    /////////////////////////////////////////////////////////////////////////////////////
274
    unsigned int  stopwatchStopAndGetResult()
275
    {
276
        return static_cast<unsigned int>(std::time(nullptr) - m_time);
277
    }
278
};
279
280
enum class STATE {
281
    OFF,
282
    ON,
283
    UNKNOWN,
284
    PLAY,
285
    PAUSE,
286
    STOP,
287
    ACTIVE,
288
    DEACTIVE,
289
    WORKING,
290
    DEFINE,
291
    UNDEFINE,
292
    LOCK,
293
    UNLOCK,
294
    EMPTY,
295
    FULL,
296
    SEND_OK,
297
    SEND_NOK
298
    //WARNING remember add new state to stateToString() usefull.cpp
299
};
300
301
302
std::string stateToString(STATE s);
303
STATE stringToState(const std::string& s);
304
305
#endif
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_help_BT.cpp
Line
Count
Source
1
#include "../command_help.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_help_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_help_Class_fixture()
8
3
    {
9
3
10
3
    }
11
12
protected:
13
    std::unique_ptr<command_help> test_command_help;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
17
3
    {
18
3
        iDomTOOLS_ClassTest::SetUp();
19
3
        test_command_help = std::make_unique <command_help> ("help");
20
3
    }
21
22
    void TearDown() final
23
3
    {
24
3
        iDomTOOLS_ClassTest::TearDown();
25
3
    }
26
};
27
28
TEST_F(command_help_Class_fixture, all)
29
1
{
30
1
    std::unique_ptr<commandHandlerRoot> chr = std::make_unique<commandHandlerRoot>(&test_my_data);
31
1
    test_v.push_back("help");
32
1
    auto size = test_command_help->execute(test_v,&test_my_data).size();
33
1
    EXPECT_EQ(size,4376);
34
1
}
35
36
TEST_F(command_help_Class_fixture, one)
37
1
{
38
1
    std::unique_ptr<commandHandlerRoot> chr = std::make_unique<commandHandlerRoot>(&test_my_data);
39
1
    test_v.push_back("help");
40
1
    test_v.push_back("ok");
41
1
    auto ret = test_command_help->execute(test_v,&test_my_data);
42
1
    EXPECT_STREQ(ret.c_str(),"ok - confirmation msg server response: END \n");
43
1
}
44
45
TEST_F(command_help_Class_fixture, nonExistingCommand)
46
1
{
47
1
    std::unique_ptr<commandHandlerRoot> chr = std::make_unique<commandHandlerRoot>(&test_my_data);
48
1
    test_v.push_back("help");
49
1
    test_v.push_back("okdoki");
50
1
    auto ret = test_command_help->execute(test_v,&test_my_data);
51
1
    EXPECT_STREQ(ret.c_str(),"unknown command: okdoki help note not found");
52
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDom_server_OOP.h
Line
Count
Source
1
#ifndef GLOBAL_H
2
#define GLOBAL_H
3
4
#include <iostream>
5
#include <fstream>
6
#include <string>
7
#include <cstdlib>
8
#include <pthread.h>
9
#include <stdio.h>
10
#include <stdlib.h>
11
#include <sys/socket.h>
12
#include <sys/types.h>
13
#include <netinet/in.h>
14
#include <vector>
15
#include <thread>
16
#include <arpa/inet.h>
17
#include <netinet/in.h>
18
#include <unistd.h>
19
#include <sys/fcntl.h>
20
#include <unistd.h>
21
#include <errno.h>
22
#include <signal.h>
23
#include <time.h>
24
#include <wiringPi.h>
25
#include <chrono>
26
#include <array>
27
28
// MOJE BIBLIOTEKI
29
#include "KEY/key.h"
30
#include "logger/logger.hpp"
31
#include "files_tree/files_tree.h"
32
#include "menu_tree/menu_tree.h"
33
#include "LCD_c/lcd_c.h"
34
#include "command/command.h"
35
#include "../libs/event_counters/event_counters_handler.h"
36
#include "iDomTools/idomtools.h"
37
#include "iDomStatus/idomstatus.h"
38
#include "iDomSaveState/idom_save_state.h"
39
40
40
#define log_file_cout  f_log //std::cout zmien f_log na std::cout i bedzie wypisywac na ekran
41
16
#define log_file_mutex f_log
42
43
enum class iDomStateEnum{
44
    CLOSE = 0,
45
    RELOAD,
46
    ERROR,
47
    WORKING,
48
    HARD_RELOAD
49
};
50
51
namespace iDomConst
52
{
53
constexpr int MAX_CONNECTION = 10;
54
constexpr int FREE  = 1;
55
constexpr int RS232 = 11;
56
constexpr int CLOCK = 12;
57
constexpr int ok    = 0;
58
constexpr int GPIO_SPIK = 21;
59
constexpr int GPIO_PRINTER = 22;
60
constexpr int BUTTON_PIN = 25;
61
}
62
struct ALERT
63
{
64
    Clock time;
65
    STATE state = STATE::DEACTIVE;
66
    unsigned int fromVolume = 48;
67
    unsigned int toVolume = 58;
68
    unsigned int radioID = 8;
69
};
70
71
extern std::string _logfile;
72
extern Logger log_file_mutex;
73
extern std::string buffer;
74
75
enum class TEMPERATURE_STATE;
76
enum class PILOT_KEY;
77
78
struct MPD_info{
79
    std::string title   = "NULL";
80
    std::string radio   = "NULL";
81
    std::string artist  = "NULL";
82
    int volume = 0;
83
    bool isPlay = false;
84
    int currentSongID = 0;
85
    std::vector <std::string> songList = {"NULL"};
86
};
87
struct s_pointer{
88
    unsigned int *ptr_who;
89
    int32_t *ptr_buf;
90
};
91
92
struct Thread_array_struc {
93
    std::thread thread;
94
    std::thread::id thread_ID = std::thread::id(0);
95
    std::string thread_name;
96
    int thread_socket = 0;
97
};
98
99
struct address_another_servers {
100
    int id;
101
    std::string SERVER_IP;
102
};
103
104
struct FTP_SERVER{
105
    std::string URL;
106
    std::string user;
107
    std::string pass;
108
};
109
struct iDOM_STATE{
110
    STATE houseState = STATE::UNDEFINE;
111
112
};
113
114
struct config{
115
    std::string portRS232;
116
    std::string portRS232_clock;
117
    std::string BaudRate;
118
    std::string RFLinkPort;
119
    std::string RFLinkBaudRate;
120
    int PORT;
121
    std::string SERVER_IP;
122
    std::string MPD_IP;
123
    std::string MOVIES_DB_PATH;
124
    std::string MENU_PATH;
125
    std::string THREAD_MPD   = "NULL";
126
    std::string THREAD_IRDA  = "NULL";
127
    std::string THREAD_CRON  = "NULL";
128
    std::string THREAD_RS232 = "NULL";
129
    std::string THREAD_DUMMY = "NULL";
130
    std::string TS_KEY= " gg ";
131
    std::string cameraLedON = "";
132
    std::string cameraLedOFF ="";
133
    std::string cameraURL="";
134
    std::string facebookAccessToken = "";
135
    std::string viberToken = "NULL";
136
    std::string viberAvatar;
137
    std::vector <std::string> viberReceiver;
138
    std::string viberSender;
139
    std::string radio433MHzConfigFile;
140
    std::string omxplayerFile = "NULL";
141
    int ID_server = 0;
142
    int v_delay;
143
    bool encrypted = true;
144
145
    FTP_SERVER ftpServer;
146
    std::string lightningApiURL = "NULL";
147
    std::string saveFilePath = "NULL";
148
};
149
150
struct LED_Strip{
151
    std::string from;
152
    std::string to;
153
    std::string R;
154
    std::string G;
155
    std::string B;
156
    std::string colorName;
157
158
    LED_Strip (int from, int to, int r, int g, int b, std::string colorName = "NULL"):from(std::to_string(from)),
159
        to(std::to_string(to)),
160
        R(std::to_string(r)),
161
        G(std::to_string(g)),
162
        B(std::to_string(b)),
163
        colorName(colorName)
164
    {
165
166
    }
167
    LED_Strip (const std::string& from,
168
               const std::string& to,
169
               const std::string& r,
170
               const std::string& g,
171
               const std::string& b,
172
               const std::string& colorName = "NULL"):
173
        from(from),
174
        to(to),
175
        R(r),
176
        G(g),
177
        B(b),
178
        colorName(colorName)
179
    {
180
181
    }
182
183
    void set (const std::string& from,
184
              const std::string& to,
185
              const std::string& r,
186
              const std::string& g,
187
              const std::string& b,
188
              const std::string& colorName = "NULL")
189
    {
190
        this->from =from;
191
        this->to = to;
192
        R = r;
193
        G = g;
194
        B = b;
195
        this->colorName =colorName;
196
    }
197
198
    void set (int from, int to, int r, int g, int b, std::string colorName = "NULL"){
199
        this->from = std::to_string(from);
200
        this->to = std::to_string(to);
201
        R = std::to_string(r);
202
        G = std::to_string(g);
203
        B = std::to_string(b);
204
        this->colorName =colorName;
205
    }
206
207
    std::string getColorName() const{
208
        return colorName;
209
    }
210
211
    std::string get(unsigned int _from, unsigned int _to) const{
212
        if (_from != 0 || _to != 60){
213
            return "LED:["+std::to_string(_from)+"-"+std::to_string(_to)+"-"+R+"-"+G+"-"+B+"];";
214
        }
215
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
216
    }
217
218
    std::string makeCommand(const std::string& from,
219
                            const std::string& to,
220
                            const std::string& R,
221
                            const std::string& G,
222
                            const std::string& B){
223
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
224
    }
225
};
226
227
struct pilot_led{
228
    unsigned int counter=0;
229
    std::vector<LED_Strip> colorLED   = { LED_Strip(1,60,237,145,33 ,"carrot orange"),
230
                                          LED_Strip(1,60,255,0,0    ,"red"),
231
                                          LED_Strip(1,60,0,255,0    ,"green"),
232
                                          LED_Strip(1,60,0,0,255    ,"blue"),
233
                                          LED_Strip(1,60,255,255,255,"white"),
234
                                          LED_Strip(1,60,255,255,0  ,"yellow"),
235
                                          LED_Strip(1,60,0,255,255  ,"cyan"),
236
                                          LED_Strip(1,60,255,0,255  ,"magenta")
237
                                        };
238
};
239
240
class command; // for struc thread_data req
241
class iDomTOOLS;
242
class RADIO_EQ_CONTAINER;
243
class RFLinkHandler;
244
245
struct thread_data{
246
    int s_client_sock;
247
    struct sockaddr_in from;
248
    struct config *server_settings = NULL;
249
    struct s_pointer pointer;
250
    LCD_c *mainLCD = NULL;
251
    files_tree *main_tree = NULL;
252
    menu_tree *main_MENU = NULL;
253
    iDomTOOLS *main_iDomTools = NULL;
254
    RFLinkHandler *main_RFLink = NULL;
255
    std::array<Thread_array_struc, iDomConst::MAX_CONNECTION> *main_THREAD_arr = NULL;
256
    time_t start;
257
    time_t now_time;
258
    int sleeper;
259
    std::map <std::string, std::unique_ptr <KEY> > key_map;
260
    MPD_info *ptr_MPD_info = NULL;
261
    pilot_led * ptr_pilot_led = NULL;
262
    std::map <std::string, std::unique_ptr<command> >* commandMapPtr = NULL;
263
    event_counters_handler myEventHandler;
264
    std::string encriptionKey = "40%";
265
    iDomSTATUS *main_iDomStatus;
266
    iDOM_STATE idom_all_state;
267
    ALERT alarmTime;
268
    std::shared_ptr<RADIO_EQ_CONTAINER> main_REC;
269
    iDomStateEnum iDomProgramState = iDomStateEnum::WORKING;
270
};
271
272
struct thread_data_rs232{
273
    std::string portRS232;
274
    std::string portRS232_clock;
275
    std::string BaudRate;
276
    struct s_pointer pointer;
277
};
278
279
#endif // GLOBAL_H
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_idom_BT.cpp
Line
Count
Source
1
#include <gtest/gtest.h>
2
3
#include "../command_idom.h"
4
#include "../../../functions/functions.h"
5
#include "../../../RADIO_433_eq/radio_433_eq.h"
6
#include "../../../433MHz/RFLink/rflinkhandler.h"
7
#include "../../../iDomTools/test/iDomTools_fixture.h"
8
#include "../../../thread_functions/iDom_thread.h"
9
10
class commandiDom_Class_fixture : public iDomTOOLS_ClassTest
11
{
12
public:
13
    commandiDom_Class_fixture()
14
20
    {
15
20
        this->test_command_iDom = std::nullptr_t();
16
20
        this->test_RFLink = std::nullptr_t();
17
20
    }
18
19
protected:
20
    std::vector<std::string> test_v= {"iDom"};
21
    RFLinkHandler* test_RFLink;
22
    blockQueue test_q;
23
    command_iDom* test_command_iDom;
24
25
    void SetUp() final
26
20
    {
27
20
        iDomTOOLS_ClassTest::SetUp();
28
20
29
20
        test_q._clearAll();
30
20
31
20
        test_RFLink = new RFLinkHandler(&test_my_data);
32
20
        test_command_iDom = new command_iDom("iDom");
33
20
        test_my_data.main_RFLink = test_RFLink;
34
20
        std::cout << "commandiDom_Class_fixture SetUp" << std::endl;
35
20
    }
36
37
    void TearDown() final
38
20
    {
39
20
        iDomTOOLS_ClassTest::TearDown();
40
20
        delete test_RFLink;
41
20
        delete test_command_iDom;
42
20
        std::cout << "commandiDom_Class_fixture TearDown" << std::endl;
43
20
    }
44
};
45
46
TEST_F(commandiDom_Class_fixture, getName)
47
1
{
48
1
    EXPECT_THAT(test_command_iDom->getCommandName(),testing::HasSubstr("iDom"));
49
1
}
50
51
TEST_F(commandiDom_Class_fixture, help)
52
1
{
53
1
    std::string helpStr = test_command_iDom->help();
54
1
    EXPECT_THAT(helpStr,testing::HasSubstr("iDom"));
55
1
    std::cout << "test " << helpStr.size() << std::endl;
56
1
    EXPECT_EQ(helpStr.size(),1189);
57
1
}
58
59
TEST_F(commandiDom_Class_fixture, less_param)
60
1
{
61
1
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
62
1
    EXPECT_THAT(retStr,testing::HasSubstr("need parameter!"));
63
1
}
64
TEST_F(commandiDom_Class_fixture, unknonw_para)
65
1
{
66
1
    test_v.push_back("fake");
67
1
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
68
1
    EXPECT_THAT(retStr,testing::HasSubstr("iDom - unknown parameter:"));
69
1
}
70
71
TEST_F(commandiDom_Class_fixture, speakers)
72
1
{
73
1
    test_my_data.main_iDomTools->unlockHome();
74
1
    //////////////// fake command
75
1
    test_v.push_back("speakers");
76
1
    test_v.push_back("fake");
77
1
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
78
1
    EXPECT_THAT(retStr,testing::HasSubstr("unknow speakers action: fake"));
79
1
    ///////////////// ON
80
1
    test_my_data.main_iDomStatus->setObjectState("speakers",STATE::UNDEFINE);
81
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("speakers"), STATE::UNDEFINE);
82
1
    test_v.clear();
83
1
    test_v.push_back("iDom");
84
1
    test_v.push_back("speakers");
85
1
    test_v.push_back("ON");
86
1
    retStr = test_command_iDom->execute(test_v, &test_my_data);
87
1
    EXPECT_THAT(retStr,testing::HasSubstr("speakers ON"));
88
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("speakers"), STATE::ON);
89
1
    ///////////////// OFF
90
1
    test_v.clear();
91
1
    test_v.push_back("iDom");
92
1
    test_v.push_back("speakers");
93
1
    test_v.push_back("OFF");
94
1
    retStr = test_command_iDom->execute(test_v, &test_my_data);
95
1
    EXPECT_THAT(retStr,testing::HasSubstr("speakers OFF"));
96
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("speakers"), STATE::OFF);
97
1
}
98
99
TEST_F(commandiDom_Class_fixture, sunset_sunrise)
100
1
{
101
1
    test_v.clear();
102
1
    test_v.push_back("iDom");
103
1
    test_v.push_back("sunset");
104
1
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
105
1
    std::cout << "retString: " << retStr << std::endl;
106
1
    EXPECT_THAT(retStr,testing::HasSubstr("Sunset time:"));
107
1
108
1
    test_v.clear();
109
1
    test_v.push_back("iDom");
110
1
    test_v.push_back("sunrise");
111
1
    retStr = test_command_iDom->execute(test_v, &test_my_data);
112
1
    std::cout << "retString: " << retStr << std::endl;
113
1
    EXPECT_THAT(retStr,testing::HasSubstr("Sunrise time:"));
114
1
}
115
116
TEST_F(commandiDom_Class_fixture, day_lenght)
117
1
{
118
1
    test_v.clear();
119
1
    test_v.push_back("iDom");
120
1
    test_v.push_back("day");
121
1
    test_v.push_back("lenght");
122
1
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
123
1
    std::cout << "retString: " << retStr << std::endl;
124
1
    EXPECT_THAT(retStr,testing::HasSubstr("Day Lenght :"));
125
1
}
126
127
TEST_F(commandiDom_Class_fixture, sun)
128
1
{
129
1
    test_v.clear();
130
1
    test_v.push_back("iDom");
131
1
    test_v.push_back("sun");
132
1
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
133
1
    std::cout << "retString: " << retStr << std::endl;
134
1
    EXPECT_THAT(retStr,testing::HasSubstr("Day Lenght :"));
135
1
}
136
137
TEST_F(commandiDom_Class_fixture, sysinfo)
138
1
{
139
1
    test_v.clear();
140
1
    test_v.push_back("iDom");
141
1
    test_v.push_back("sysinfo");
142
1
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
143
1
    std::cout << "retString: " << retStr << std::endl;
144
1
    EXPECT_THAT(retStr,testing::HasSubstr("free RAM"));
145
1
}
146
147
TEST_F(commandiDom_Class_fixture, temperature)
148
1
{
149
1
    TEST_DATA::return_send_to_arduino = "-12:22";
150
1
    test_v.clear();
151
1
    test_v.push_back("iDom");
152
1
    test_v.push_back("temperature");
153
1
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
154
1
    std::cout << "retString: " << retStr << std::endl;
155
1
    EXPECT_THAT(retStr,testing::HasSubstr("-12:22"));
156
1
157
1
    test_v.clear();
158
1
    test_v.push_back("iDom");
159
1
    test_v.push_back("temperature");
160
1
    test_v.push_back("stats");
161
1
    test_v.push_back("insideee");
162
1
    retStr = test_command_iDom->execute(test_v, &test_my_data);
163
1
    std::cout << "retString: " << retStr << std::endl;
164
1
    EXPECT_THAT(retStr,testing::HasSubstr("not found!"));
165
1
}
166
167
TEST_F(commandiDom_Class_fixture, text)
168
1
{
169
1
    TEST_DATA::return_send_to_arduino = "-12:22";
170
1
    test_v.clear();
171
1
    test_v.push_back("iDom");
172
1
    test_v.push_back("text");
173
1
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
174
1
    std::cout << "retString: " << retStr << std::endl;
175
1
    EXPECT_THAT(retStr,testing::HasSubstr("Godzina"));
176
1
}
177
178
TEST_F(commandiDom_Class_fixture, lock_unlock)
179
1
{
180
1
    test_v.clear();
181
1
    test_v.push_back("iDom");
182
1
    test_v.push_back("lock");
183
1
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
184
1
    std::cout << "retString: " << retStr << std::endl;
185
1
    EXPECT_EQ(test_my_data.idom_all_state.houseState, STATE::LOCK);
186
1
187
1
    test_v.clear();
188
1
    test_v.push_back("iDom");
189
1
    test_v.push_back("unlock");
190
1
    retStr = test_command_iDom->execute(test_v, &test_my_data);
191
1
    std::cout << "retString: " << retStr << std::endl;
192
1
    EXPECT_EQ(test_my_data.idom_all_state.houseState, STATE::UNLOCK);
193
1
}
194
195
TEST_F(commandiDom_Class_fixture, t_230V)
196
1
{
197
1
    test_my_data.main_iDomTools->unlockHome();
198
1
    //////////////// fake command
199
1
    test_v.push_back("230V");
200
1
    test_v.push_back("fake");
201
1
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
202
1
    EXPECT_THAT(retStr,testing::HasSubstr("wrong paramiter"));
203
1
    ///////////////// ON
204
1
    test_my_data.main_iDomStatus->setObjectState("printer",STATE::UNDEFINE);
205
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("printer"), STATE::UNDEFINE);
206
1
    test_v.clear();
207
1
    test_v.push_back("iDom");
208
1
    test_v.push_back("230V");
209
1
    test_v.push_back("ON");
210
1
    retStr = test_command_iDom->execute(test_v, &test_my_data);
211
1
    std::cout << "retString: " << retStr << std::endl;
212
1
    EXPECT_THAT(retStr,testing::HasSubstr("230V ON"));
213
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("printer"), STATE::ON);
214
1
    ///////////////// OFF
215
1
    test_v.clear();
216
1
    test_v.push_back("iDom");
217
1
    test_v.push_back("230V");
218
1
    test_v.push_back("OFF");
219
1
    retStr = test_command_iDom->execute(test_v, &test_my_data);
220
1
    std::cout << "retString: " << retStr << std::endl;
221
1
    EXPECT_THAT(retStr,testing::HasSubstr("230V OFF"));
222
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("printer"), STATE::OFF);
223
1
}
224
225
TEST_F(commandiDom_Class_fixture, smog)
226
1
{
227
1
    test_v.clear();
228
1
    test_v.push_back("iDom");
229
1
    test_v.push_back("smog");
230
1
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
231
1
    std::cout << "retString: " << retStr << std::endl;
232
1
    EXPECT_THAT(retStr,testing::HasSubstr(" mg/m^3"));
233
1
}
234
235
TEST_F(commandiDom_Class_fixture, say)
236
1
{
237
1
    Clock::setTime_forBT_usage(23,23);
238
1
    TEST_DATA::return_send_to_arduino = "-3:6";
239
1
    test_v.clear();
240
1
    test_v.push_back("iDom");
241
1
    test_v.push_back("say");
242
1
    test_v.push_back("dummy");
243
1
    test_v.push_back("dummy");
244
1
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
245
1
    std::cout << "retString: " << retStr << std::endl;
246
1
    //EXPECT_THAT(retStr,testing::HasSubstr("sad"));
247
1
}
248
TEST_F(commandiDom_Class_fixture, wifi)
249
1
{
250
1
    TEST_DATA::return_httpPost = "ok";
251
1
    test_v.clear();
252
1
    test_v.push_back("iDom");
253
1
    test_v.push_back("wifi");
254
1
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
255
1
    std::cout << "retString: " << retStr << std::endl;
256
1
    EXPECT_THAT(retStr,testing::HasSubstr("ok"));
257
1
}
258
259
TEST_F(commandiDom_Class_fixture, lightning)
260
1
{
261
1
    test_v.clear();
262
1
    test_v.push_back("iDom");
263
1
    test_v.push_back("lightning");
264
1
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
265
1
    std::cout << "retString: " << retStr << std::endl;
266
1
    EXPECT_THAT(retStr,testing::HasSubstr("bool: "));
267
1
}
268
269
TEST_F(commandiDom_Class_fixture, camera)
270
1
{
271
1
    test_my_data.server_settings->cameraLedOFF = "cameraOFF";
272
1
    test_my_data.server_settings->cameraLedON = "cameraON";
273
1
274
1
    Clock::setTime_forBT_usage(23,23);
275
1
    test_v.clear();
276
1
    test_v.push_back("iDom");
277
1
    test_v.push_back("camera");
278
1
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
279
1
    std::cout << "retString: " << retStr << std::endl;
280
1
    EXPECT_STREQ(retStr.c_str(),"not enough parameters");
281
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("cameraLED"),STATE::UNKNOWN);
282
1
    ////////////////////////////////////////// ON
283
1
    TEST_DATA::return_httpPost = "ok.\n";
284
1
    test_v.clear();
285
1
    test_v.push_back("iDom");
286
1
    test_v.push_back("camera");
287
1
    test_v.push_back("LED");
288
1
289
1
    test_v.push_back("ON");
290
1
    retStr = test_command_iDom->execute(test_v, &test_my_data);
291
1
    std::cout << "retString: " << retStr << std::endl;
292
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("cameraLED"),STATE::ON);
293
1
    EXPECT_STREQ(retStr.c_str(),"led DONE");
294
1
    ////////////////////////////////////////// OFF
295
1
    TEST_DATA::return_httpPost = "ok.\n";
296
1
    test_v.clear();
297
1
    test_v.push_back("iDom");
298
1
    test_v.push_back("camera");
299
1
    test_v.push_back("LED");
300
1
301
1
    test_v.push_back("OFF");
302
1
    retStr = test_command_iDom->execute(test_v, &test_my_data);
303
1
    std::cout << "retString: " << retStr << std::endl;
304
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("cameraLED"),STATE::OFF);
305
1
    EXPECT_STREQ(retStr.c_str(),"led DONE");
306
1
}
307
308
TEST_F(commandiDom_Class_fixture, LED)
309
1
{
310
1
    test_my_data.main_iDomTools->unlockHome();
311
1
312
1
    test_v.clear();
313
1
    test_v.push_back("iDom");
314
1
    test_v.push_back("LED");
315
1
    test_v.push_back("33");
316
1
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
317
1
    std::cout << "retString: " << retStr << std::endl;
318
1
    EXPECT_THAT(retStr,testing::HasSubstr("need more parameter from-to-R-G-B"));
319
1
320
1
    ///////////////////////////////////// OFF
321
1
    TEST_DATA::return_send_to_arduino = "led OFF";
322
1
323
1
    test_v.clear();
324
1
    test_v.push_back("iDom");
325
1
    test_v.push_back("LED");
326
1
    test_v.push_back("OFF");
327
1
    retStr = test_command_iDom->execute(test_v, &test_my_data);
328
1
    std::cout << "retString: " << retStr << std::endl;
329
1
    EXPECT_THAT(retStr,testing::HasSubstr("led OFF"));
330
1
}
331
TEST_F(commandiDom_Class_fixture, kodi)
332
1
{
333
1
    test_my_data.main_iDomStatus->setObjectState("KODI",STATE::ACTIVE);
334
1
    test_v.clear();
335
1
    test_v.push_back("iDom");
336
1
    test_v.push_back("KODI");
337
1
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
338
1
339
1
    std::cout << "retString: " << retStr << std::endl;
340
1
    EXPECT_STREQ(retStr.c_str(),"kodi already run");
341
1
342
1
    test_my_data.main_iDomStatus->setObjectState("KODI",STATE::DEACTIVE);
343
1
    test_my_data.main_iDomStatus->setObjectState("music",STATE::PLAY);
344
1
    test_my_data.main_iDomStatus->setObjectState("speakers",STATE::ON);
345
1
346
1
    std::array<Thread_array_struc,iDomConst::MAX_CONNECTION> test_ThreadArrayStruc;
347
1
348
11
    for (int i = 0 ; i < iDomConst::MAX_CONNECTION; i++)
349
10
        test_ThreadArrayStruc.at(i).thread_socket = i+1;
350
1
    test_ThreadArrayStruc.at(3).thread_socket = 0;
351
1
    test_my_data.main_THREAD_arr = &test_ThreadArrayStruc;
352
1
353
1
    test_v.clear();
354
1
    test_v.push_back("iDom");
355
1
    test_v.push_back("KODI");
356
1
    retStr = test_command_iDom->execute(test_v, &test_my_data);
357
1
358
1
    sleep(1);
359
1
    std::cout << "retString: " << retStr << std::endl;
360
1
    EXPECT_THAT(retStr,testing::HasSubstr("STARTED"));
361
1
362
11
    for (int i = 0 ; i < iDomConst::MAX_CONNECTION; i++)
363
10
        test_ThreadArrayStruc[i].thread_socket = -1;
364
1
    test_v.clear();
365
1
    test_v.push_back("iDom");
366
1
    test_v.push_back("KODI");
367
1
    retStr = test_command_iDom->execute(test_v, &test_my_data);
368
1
369
1
    std::cout << "retString: " << retStr << std::endl;
370
1
    EXPECT_STREQ(retStr.c_str(),"not free space to new thread");
371
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/logger/logger.hpp
Line
Count
Source
1
/*
2
 * logger.hpp
3
 *
4
 *
5
 * Logger Library Header
6
 *
7
 *
8
 * Copyright (C) 2013-2014  Bryant Moscon - bmoscon@gmail.com
9
 *
10
 * Permission is hereby granted, free of charge, to any person obtaining a copy
11
 * of this software and associated documentation files (the "Software"), to
12
 * deal in the Software without restriction, including without limitation the
13
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
14
 * sell copies of the Software, and to permit persons to whom the Software is
15
 * furnished to do so, subject to the following conditions:
16
 *
17
 * 1. Redistributions of source code must retain the above copyright notice,
18
 *    this list of conditions, and the following disclaimer.
19
 *
20
 * 2. Redistributions in binary form must reproduce the above copyright notice,
21
 *    this list of conditions and the following disclaimer in the documentation
22
 *    and/or other materials provided with the distribution, and in the same
23
 *    place and form as other copyright, license and disclaimer information.
24
 *
25
 * 3. The end-user documentation included with the redistribution, if any, must
26
 *    include the following acknowledgment: "This product includes software
27
 *    developed by Bryant Moscon (http://www.bryantmoscon.org/)", in the same
28
 *    place and form as other third-party acknowledgments. Alternately, this
29
 *    acknowledgment may appear in the software itself, in the same form and
30
 *    location as other such third-party acknowledgments.
31
 *
32
 * 4. Except as contained in this notice, the name of the author, Bryant Moscon,
33
 *    shall not be used in advertising or otherwise to promote the sale, use or
34
 *    other dealings in this Software without prior written authorization from
35
 *    the author.
36
 *
37
 *
38
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
41
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
42
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
44
 * THE SOFTWARE.
45
 *
46
 */
47
#ifndef __LOGGER__
48
#define __LOGGER__
49
50
#include <fstream>
51
#include <cassert>
52
#include <ctime>
53
#include <sstream>
54
55
// Log levels
56
typedef enum {
57
    US =0,
58
    VERBOSE,
59
    DEBUG,
60
    INFO,
61
    WARNING,
62
    ERROR,
63
    CRITICAL,
64
    FATAL
65
} logger_level;
66
67
class Logger : public std::ostringstream {
68
public:
69
70
    explicit Logger(const char *f);
71
    explicit Logger(const std::string& f);
72
    Logger (const Logger &);
73
    Logger &operator= (const Logger &);
74
    ~Logger();
75
    static pthread_mutex_t mutex_log;
76
77
    void set_level(const logger_level& level);
78
    void flush();
79
    void mutex_lock();
80
    void mutex_unlock();
81
82
    template <typename T>
83
    Logger& operator<<(const T& t)
84
8
    {
85
8
        *static_cast<std::ostringstream *>(this) << t;
86
8
        return (*this);
87
8
    }
88
89
    Logger& operator<<(const logger_level& level);
90
    typedef Logger& (* LoggerManip)(Logger&);
91
    Logger& operator<<(LoggerManip m);
92
93
private:
94
    std::string get_time() const;
95
    inline const char* level_str(const logger_level& level);
96
public:
97
    std::ofstream _file;
98
private:
99
    std::ostream& _log;
100
    logger_level _level;
101
    logger_level _line_level;
102
};
103
104
105
namespace std { 
106
inline Logger& endl(Logger& out)
107
{
108
    out.put('\n');
109
    out.flush();
110
    return (out);
111
}
112
}// end namespace std
113
114
#endif
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_ip_BT.cpp
Line
Count
Source
1
#include "../command_ip.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_ip_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_ip_Class_fixture()
8
1
    {
9
1
10
1
    }
11
12
protected:
13
    std::unique_ptr<command_ip> test_command_ip;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
17
1
    {
18
1
        iDomTOOLS_ClassTest::SetUp();
19
1
        test_command_ip =  std::make_unique <command_ip> ("ip");
20
1
    }
21
22
    void TearDown() final
23
1
    {
24
1
        iDomTOOLS_ClassTest::TearDown();
25
1
    }
26
};
27
28
TEST_F(command_ip_Class_fixture, main)
29
1
{
30
1
    test_my_data.server_settings->SERVER_IP = "100.001.1.0";
31
1
    test_v.push_back("ip");
32
1
    auto ret = test_command_ip->execute(test_v,&test_my_data);
33
1
    EXPECT_STREQ(ret.c_str(),"iDom server IP: 100.001.1.0");
34
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/ftplibpp/ftplib.h
Line
Count
Source (jump to first uncovered line)
1
/***************************************************************************
2
                          ftplib.h  -  description
3
                             -------------------
4
    begin                : Son Jul 27 2003
5
    copyright            : (C) 2013 by magnus kulke
6
    email                : mkulke@gmail.com
7
 ***************************************************************************/
8
9
/***************************************************************************
10
 *                                                                         *
11
 *   This program is free software; you can redistribute it and/or modify  *
12
 *   it under the terms of the GNU Lesser General Public License as        * 
13
 *   published by the Free Software Foundation; either version 2.1 of the  *
14
 *   License, or (at your option) any later version.                       *
15
 *                                                                         *
16
 ***************************************************************************/
17
 
18
/***************************************************************************
19
 * Note: ftplib, on which ftplibpp was originally based upon used to be    *
20
 * licensed as GPL 2.0 software, as of Jan. 26th 2013 its author Thomas    *
21
 * Pfau allowed the distribution of ftplib via LGPL. Thus the license of   *
22
 * ftplibpp changed aswell.                                                *
23
 ***************************************************************************/
24
 
25
#ifndef FTPLIB_H
26
#define FTPLIB_H
27
28
#if defined(_WIN32)
29
30
#if BUILDING_DLL
31
# define DLLIMPORT __declspec (dllexport)
32
#else /* Not BUILDING_DLL */
33
# define DLLIMPORT __declspec (dllimport)
34
#endif /* Not BUILDING_DLL */
35
36
#include <time.h>
37
#endif
38
39
#ifndef _WIN32
40
#include <unistd.h>
41
#include <sys/time.h>
42
#endif
43
44
#ifdef NOLFS
45
#define off64_t long
46
#endif
47
48
#if defined(__APPLE__)
49
#define off64_t __darwin_off_t
50
#define fseeko64 fseeko
51
#define fopen64 fopen
52
#endif
53
54
#ifndef NOSSL
55
#include <openssl/ssl.h>
56
#endif
57
58
#ifndef _FTPLIB_SSL_CLIENT_METHOD_
59
#define _FTPLIB_SSL_CLIENT_METHOD_ TLSv1_2_client_method
60
#endif//_FTPLIB_SSL_CLIENT_METHOD_
61
62
using namespace std;
63
64
/**
65
  *@author mkulke
66
  */
67
68
typedef int (*FtpCallbackXfer)(off64_t xfered, void *arg);
69
typedef int (*FtpCallbackIdle)(void *arg);
70
typedef void (*FtpCallbackLog)(char *str, void* arg, bool out);
71
72
#ifndef NOSSL
73
typedef bool (*FtpCallbackCert)(void *arg, X509 *cert);
74
#endif
75
76
struct ftphandle {
77
  char *cput,*cget;
78
  int handle;
79
  int cavail,cleft;
80
  char *buf;
81
  int dir;
82
  ftphandle *ctrl;
83
  int cmode;
84
  struct timeval idletime;
85
  FtpCallbackXfer xfercb;
86
  FtpCallbackIdle idlecb;
87
  FtpCallbackLog logcb;
88
  void *cbarg;
89
  off64_t xfered;
90
  off64_t cbbytes;
91
  off64_t xfered1;
92
  char response[256];
93
#ifndef NOSSL
94
  SSL* ssl;
95
  SSL_CTX* ctx;
96
  BIO* sbio;
97
  int tlsctrl;
98
  int tlsdata;
99
  FtpCallbackCert certcb;
100
#endif
101
  off64_t offset;
102
  bool correctpasv;
103
};
104
105
#if defined(_WIN32)  
106
class DLLIMPORT ftplib {
107
#else
108
class ftplib {
109
#endif
110
public:
111
112
  enum accesstype
113
  {
114
    dir = 1,
115
    dirverbose,
116
    fileread,
117
    filewrite,
118
    filereadappend,
119
    filewriteappend
120
  }; 
121
122
  enum transfermode
123
  {
124
    ascii = 'A',
125
    image = 'I'
126
  };
127
128
  enum connmode
129
  {
130
    pasv = 1,
131
    port
132
  };
133
134
  enum fxpmethod
135
  {
136
    defaultfxp = 0,
137
        alternativefxp
138
  };
139
140
    enum dataencryption
141
    {
142
        unencrypted = 0,
143
        secure
144
    };
145
146
  ftplib();
147
  ~ftplib();
148
    char* LastResponse();
149
    int Connect(const char *host);
150
    int Login(const char *user, const char *pass);
151
    int Site(const char *cmd);
152
    int Raw(const char *cmd);
153
    int SysType(char *buf, int max);
154
    int Mkdir(const char *path);
155
    int Chdir(const char *path);
156
    int Cdup();
157
    int Rmdir(const char *path);
158
    int Pwd(char *path, int max);
159
    int Nlst(const char *outputfile, const char *path);
160
    int Dir(const char *outputfile, const char *path);
161
    int Size(const char *path, int *size, transfermode mode);
162
    int ModDate(const char *path, char *dt, int max);
163
    int Get(const char *outputfile, const char *path, transfermode mode, off64_t offset = 0);
164
    int Put(const char *inputfile, const char *path, transfermode mode, off64_t offset = 0);
165
    int Rename(const char *src, const char *dst);
166
    int Delete(const char *path);
167
#ifndef NOSSL    
168
  int SetDataEncryption(dataencryption enc);
169
    int NegotiateEncryption();
170
  void SetCallbackCertFunction(FtpCallbackCert pointer);
171
#endif
172
    int Quit();
173
    void SetCallbackIdleFunction(FtpCallbackIdle pointer);
174
    void SetCallbackLogFunction(FtpCallbackLog pointer);
175
  void SetCallbackXferFunction(FtpCallbackXfer pointer);
176
  void SetCallbackArg(void *arg);
177
    void SetCallbackBytes(off64_t bytes);
178
0
  void SetCorrectPasv(bool b) { mp_ftphandle->correctpasv = b; };
179
    void SetCallbackIdletime(int time);
180
    void SetConnmode(connmode mode);
181
    static int Fxp(ftplib* src, ftplib* dst, const char *pathSrc, const char *pathDst, transfermode mode, fxpmethod method);
182
    
183
  ftphandle* RawOpen(const char *path, accesstype type, transfermode mode);
184
  int RawClose(ftphandle* handle); 
185
  int RawWrite(void* buf, int len, ftphandle* handle);
186
  int RawRead(void* buf, int max, ftphandle* handle); 
187
188
private:
189
    ftphandle* mp_ftphandle;
190
191
    int FtpXfer(const char *localfile, const char *path, ftphandle *nControl, accesstype type, transfermode mode);
192
    int FtpOpenPasv(ftphandle *nControl, ftphandle **nData, transfermode mode, int dir, char *cmd);
193
    int FtpSendCmd(const char *cmd, char expresp, ftphandle *nControl);
194
    int FtpAcceptConnection(ftphandle *nData, ftphandle *nControl);
195
    int FtpOpenPort(ftphandle *nControl, ftphandle **nData, transfermode mode, int dir, char *cmd);
196
    int FtpRead(void *buf, int max, ftphandle *nData);
197
    int FtpWrite(void *buf, int len, ftphandle *nData);
198
    int FtpAccess(const char *path, accesstype type, transfermode mode, ftphandle *nControl, ftphandle **nData);
199
    int FtpClose(ftphandle *nData);
200
  
201
  int socket_wait(ftphandle *ctl);
202
    int readline(char *buf,int max,ftphandle *ctl);
203
    int writeline(char *buf, int len, ftphandle *nData);
204
    int readresp(char c, ftphandle *nControl);
205
  
206
  void ClearHandle();
207
  int CorrectPasvResponse(unsigned char *v);
208
};
209
210
#endif
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_log_BT.cpp
Line
Count
Source
1
#include "../command_log.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_log_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_log_Class_fixture()
8
1
    {
9
1
10
1
    }
11
12
protected:
13
    std::unique_ptr<command_log> test_command_log;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
17
1
    {
18
1
        iDomTOOLS_ClassTest::SetUp();
19
1
        test_command_log = std::make_unique <command_log> ("log");
20
1
    }
21
22
    void TearDown() final
23
1
    {
24
1
        iDomTOOLS_ClassTest::TearDown();
25
1
    }
26
};
27
28
TEST_F(command_log_Class_fixture, main)
29
1
{
30
1
    test_v.clear();
31
1
    test_v.push_back("log");
32
1
    test_v.push_back("INFOoo");
33
1
    test_v.push_back("test");
34
1
    auto ret = test_command_log->execute(test_v,&test_my_data);
35
1
    EXPECT_THAT(ret, ::testing::HasSubstr("DONE!"));
36
1
37
1
    test_v.clear();
38
1
    test_v.push_back("log");
39
1
    test_v.push_back("INFO");
40
1
    test_v.push_back("test");
41
1
    ret = test_command_log->execute(test_v,&test_my_data);
42
1
    EXPECT_THAT(ret, ::testing::HasSubstr("DONE!"));
43
1
44
1
    test_v.clear();
45
1
    test_v.push_back("log");
46
1
    test_v.push_back("DEBUG");
47
1
    test_v.push_back("test");
48
1
    ret = test_command_log->execute(test_v,&test_my_data);
49
1
    EXPECT_THAT(ret, ::testing::HasSubstr("DONE!"));
50
1
51
1
    test_v.clear();
52
1
    test_v.push_back("log");
53
1
    test_v.push_back("WARNING");
54
1
    test_v.push_back("test");
55
1
    ret = test_command_log->execute(test_v,&test_my_data);
56
1
    EXPECT_THAT(ret, ::testing::HasSubstr("DONE!"));
57
1
    test_v.clear();
58
1
    test_v.push_back("log");
59
1
    test_v.push_back("ERROR");
60
1
    test_v.push_back("test");
61
1
    ret = test_command_log->execute(test_v,&test_my_data);
62
1
    EXPECT_THAT(ret, ::testing::HasSubstr("DONE!"));
63
1
    test_v.clear();
64
1
    test_v.push_back("log");
65
1
    test_v.push_back("FATAL");
66
1
    test_v.push_back("test");
67
1
    ret = test_command_log->execute(test_v,&test_my_data);
68
1
    EXPECT_THAT(ret, ::testing::HasSubstr("DONE!"));
69
1
    test_v.clear();
70
1
    test_v.push_back("log");
71
1
    test_v.push_back("CRITICAL");
72
1
    test_v.push_back("test");
73
1
    ret = test_command_log->execute(test_v,&test_my_data);
74
1
    EXPECT_THAT(ret, ::testing::HasSubstr("DONE!"));
75
1
    test_v.clear();
76
1
    test_v.push_back("log");
77
1
    test_v.push_back("VERBOSE");
78
1
    test_v.push_back("test");
79
1
    ret = test_command_log->execute(test_v,&test_my_data);
80
1
    EXPECT_THAT(ret, ::testing::HasSubstr("DONE!"));
81
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/logger/logger.hpp
Line
Count
Source
1
/*
2
 * logger.hpp
3
 *
4
 *
5
 * Logger Library Header
6
 *
7
 *
8
 * Copyright (C) 2013-2014  Bryant Moscon - bmoscon@gmail.com
9
 *
10
 * Permission is hereby granted, free of charge, to any person obtaining a copy
11
 * of this software and associated documentation files (the "Software"), to
12
 * deal in the Software without restriction, including without limitation the
13
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
14
 * sell copies of the Software, and to permit persons to whom the Software is
15
 * furnished to do so, subject to the following conditions:
16
 *
17
 * 1. Redistributions of source code must retain the above copyright notice,
18
 *    this list of conditions, and the following disclaimer.
19
 *
20
 * 2. Redistributions in binary form must reproduce the above copyright notice,
21
 *    this list of conditions and the following disclaimer in the documentation
22
 *    and/or other materials provided with the distribution, and in the same
23
 *    place and form as other copyright, license and disclaimer information.
24
 *
25
 * 3. The end-user documentation included with the redistribution, if any, must
26
 *    include the following acknowledgment: "This product includes software
27
 *    developed by Bryant Moscon (http://www.bryantmoscon.org/)", in the same
28
 *    place and form as other third-party acknowledgments. Alternately, this
29
 *    acknowledgment may appear in the software itself, in the same form and
30
 *    location as other such third-party acknowledgments.
31
 *
32
 * 4. Except as contained in this notice, the name of the author, Bryant Moscon,
33
 *    shall not be used in advertising or otherwise to promote the sale, use or
34
 *    other dealings in this Software without prior written authorization from
35
 *    the author.
36
 *
37
 *
38
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
41
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
42
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
44
 * THE SOFTWARE.
45
 *
46
 */
47
#ifndef __LOGGER__
48
#define __LOGGER__
49
50
#include <fstream>
51
#include <cassert>
52
#include <ctime>
53
#include <sstream>
54
55
// Log levels
56
typedef enum {
57
    US =0,
58
    VERBOSE,
59
    DEBUG,
60
    INFO,
61
    WARNING,
62
    ERROR,
63
    CRITICAL,
64
    FATAL
65
} logger_level;
66
67
class Logger : public std::ostringstream {
68
public:
69
70
    explicit Logger(const char *f);
71
    explicit Logger(const std::string& f);
72
    Logger (const Logger &);
73
    Logger &operator= (const Logger &);
74
    ~Logger();
75
    static pthread_mutex_t mutex_log;
76
77
    void set_level(const logger_level& level);
78
    void flush();
79
    void mutex_lock();
80
    void mutex_unlock();
81
82
    template <typename T>
83
    Logger& operator<<(const T& t)
84
1
    {
85
1
        *static_cast<std::ostringstream *>(this) << t;
86
1
        return (*this);
87
1
    }
88
89
    Logger& operator<<(const logger_level& level);
90
    typedef Logger& (* LoggerManip)(Logger&);
91
    Logger& operator<<(LoggerManip m);
92
93
private:
94
    std::string get_time() const;
95
    inline const char* level_str(const logger_level& level);
96
public:
97
    std::ofstream _file;
98
private:
99
    std::ostream& _log;
100
    logger_level _level;
101
    logger_level _line_level;
102
};
103
104
105
namespace std { 
106
inline Logger& endl(Logger& out)
107
{
108
    out.put('\n');
109
    out.flush();
110
    return (out);
111
}
112
}// end namespace std
113
114
#endif
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_mpd_BT.cpp
Line
Count
Source
1
#include "../command_mpd.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_mpd_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_mpd_Class_fixture()
8
9
    {
9
9
10
9
    }
11
12
protected:
13
    std::unique_ptr<command_mpd> test_command_mpd;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
17
9
    {
18
9
        iDomTOOLS_ClassTest::SetUp();
19
9
        test_command_mpd = std::make_unique <command_mpd> ("mpd");
20
9
    }
21
22
    void TearDown() final
23
9
    {
24
9
        iDomTOOLS_ClassTest::TearDown();
25
9
    }
26
};
27
28
TEST_F(command_mpd_Class_fixture, unknownParameter)
29
1
{
30
1
    test_v.clear();
31
1
    test_v.push_back("mpd");
32
1
    test_v.push_back("test");
33
1
    auto ret = test_command_mpd->execute(test_v,&test_my_data);
34
1
    EXPECT_STREQ(ret.c_str(), "unknown parameter test");
35
1
36
1
 }
37
38
TEST_F(command_mpd_Class_fixture, list)
39
1
{
40
1
    test_my_data.ptr_MPD_info->songList = {"song 1","song 2","song 3"};
41
1
    test_v.clear();
42
1
    test_v.push_back("mpd");
43
1
    test_v.push_back("list");
44
1
    auto ret = test_command_mpd->execute(test_v,&test_my_data);
45
1
    EXPECT_STREQ(ret.c_str(), "song 1\nsong 2\nsong 3\n");
46
1
 }
47
48
TEST_F(command_mpd_Class_fixture, get)
49
1
{
50
1
    test_my_data.ptr_MPD_info->volume = 33;
51
1
    test_my_data.ptr_MPD_info->radio = "radio test";
52
1
    test_my_data.ptr_MPD_info->title = "title test";
53
1
54
1
    test_v.clear();
55
1
    test_v.push_back("mpd");
56
1
    test_v.push_back("get");
57
1
    test_v.push_back("volume");
58
1
59
1
    auto ret = test_command_mpd->execute(test_v,&test_my_data);
60
1
    EXPECT_STREQ(ret.c_str(), "33");
61
1
62
1
    test_v.clear();
63
1
    test_v.push_back("mpd");
64
1
    test_v.push_back("get");
65
1
    test_v.push_back("info");
66
1
67
1
    ret = test_command_mpd->execute(test_v,&test_my_data);
68
1
    EXPECT_STREQ(ret.c_str(), "radio test : title test");
69
1
 }
70
TEST_F(command_mpd_Class_fixture, volume)
71
1
{
72
1
    test_my_data.ptr_MPD_info->volume = 33;
73
1
74
1
    test_v.clear();
75
1
    test_v.push_back("mpd");
76
1
    test_v.push_back("volume");
77
1
    test_v.push_back("up");
78
1
79
1
    blockQueue test_q;
80
1
    test_q._clearAll();
81
1
82
1
    test_command_mpd->execute(test_v,&test_my_data);
83
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::VOLUP);
84
1
85
1
    test_v.clear();
86
1
    test_v.push_back("mpd");
87
1
    test_v.push_back("volume");
88
1
    test_v.push_back("down");
89
1
90
1
    test_command_mpd->execute(test_v,&test_my_data);
91
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::VOLDOWN);
92
1
93
1
    test_v.clear();
94
1
    test_v.push_back("mpd");
95
1
    test_v.push_back("volume");
96
1
    test_v.push_back("55");
97
1
98
1
    test_command_mpd->execute(test_v,&test_my_data);
99
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::VOLSET);
100
1
    EXPECT_EQ(test_my_data.ptr_MPD_info->volume, 55);
101
1
    /////// voule -gt 100%
102
1
    test_v.clear();
103
1
    test_v.push_back("mpd");
104
1
    test_v.push_back("volume");
105
1
    test_v.push_back("155");
106
1
107
1
    test_command_mpd->execute(test_v,&test_my_data);
108
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::NULL_);
109
1
    EXPECT_EQ(test_my_data.ptr_MPD_info->volume, 55);
110
1
 }
111
112
TEST_F(command_mpd_Class_fixture, pause)
113
1
{
114
1
    test_v.clear();
115
1
    test_v.push_back("mpd");
116
1
    test_v.push_back("pause");
117
1
118
1
    blockQueue test_q;
119
1
    test_q._clearAll();
120
1
121
1
    auto ret = test_command_mpd->execute(test_v,&test_my_data);
122
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::PAUSE);
123
1
    EXPECT_STREQ(ret.c_str(), "paused!");
124
1
}
125
126
TEST_F(command_mpd_Class_fixture, next)
127
1
{
128
1
    test_v.clear();
129
1
    test_v.push_back("mpd");
130
1
    test_v.push_back("next");
131
1
132
1
    blockQueue test_q;
133
1
    test_q._clearAll();
134
1
135
1
    test_command_mpd->execute(test_v,&test_my_data);
136
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::NEXT);
137
1
}
138
139
TEST_F(command_mpd_Class_fixture, prev)
140
1
{
141
1
    test_v.clear();
142
1
    test_v.push_back("mpd");
143
1
    test_v.push_back("prev");
144
1
145
1
    blockQueue test_q;
146
1
    test_q._clearAll();
147
1
148
1
    test_command_mpd->execute(test_v,&test_my_data);
149
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::PREV);
150
1
}
151
152
TEST_F(command_mpd_Class_fixture, stop)
153
1
{
154
1
    test_v.clear();
155
1
    test_v.push_back("mpd");
156
1
    test_v.push_back("stop");
157
1
158
1
    blockQueue test_q;
159
1
    test_q._clearAll();
160
1
161
1
    auto ret = test_command_mpd->execute(test_v,&test_my_data);
162
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::STOP);
163
1
    EXPECT_STREQ(ret.c_str(), "stoped!");
164
1
}
165
166
TEST_F(command_mpd_Class_fixture, play_playID)
167
1
{
168
1
    test_my_data.idom_all_state.houseState = STATE::UNLOCK;
169
1
    test_my_data.ptr_MPD_info->currentSongID = 2;
170
1
    test_my_data.ptr_MPD_info->songList = {"song 1","song 2","song 3"};
171
1
172
1
    test_v.clear();
173
1
    test_v.push_back("mpd");
174
1
    test_v.push_back("start");
175
1
176
1
    blockQueue test_q;
177
1
    test_q._clearAll();
178
1
179
1
    test_command_mpd->execute(test_v,&test_my_data);
180
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::PLAY);
181
1
182
1
    test_v.clear();
183
1
    test_v.push_back("mpd");
184
1
    test_v.push_back("start");
185
1
    test_v.push_back("3");
186
1
187
1
    test_q._clearAll();
188
1
189
1
    test_command_mpd->execute(test_v,&test_my_data);
190
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::PLAY_ID);
191
1
    EXPECT_EQ(test_my_data.ptr_MPD_info->currentSongID, 3);
192
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDom_server_OOP.h
Line
Count
Source
1
#ifndef GLOBAL_H
2
#define GLOBAL_H
3
4
#include <iostream>
5
#include <fstream>
6
#include <string>
7
#include <cstdlib>
8
#include <pthread.h>
9
#include <stdio.h>
10
#include <stdlib.h>
11
#include <sys/socket.h>
12
#include <sys/types.h>
13
#include <netinet/in.h>
14
#include <vector>
15
#include <thread>
16
#include <arpa/inet.h>
17
#include <netinet/in.h>
18
#include <unistd.h>
19
#include <sys/fcntl.h>
20
#include <unistd.h>
21
#include <errno.h>
22
#include <signal.h>
23
#include <time.h>
24
#include <wiringPi.h>
25
#include <chrono>
26
#include <array>
27
28
// MOJE BIBLIOTEKI
29
#include "KEY/key.h"
30
#include "logger/logger.hpp"
31
#include "files_tree/files_tree.h"
32
#include "menu_tree/menu_tree.h"
33
#include "LCD_c/lcd_c.h"
34
#include "command/command.h"
35
#include "../libs/event_counters/event_counters_handler.h"
36
#include "iDomTools/idomtools.h"
37
#include "iDomStatus/idomstatus.h"
38
#include "iDomSaveState/idom_save_state.h"
39
40
15
#define log_file_cout  f_log //std::cout zmien f_log na std::cout i bedzie wypisywac na ekran
41
6
#define log_file_mutex f_log
42
43
enum class iDomStateEnum{
44
    CLOSE = 0,
45
    RELOAD,
46
    ERROR,
47
    WORKING,
48
    HARD_RELOAD
49
};
50
51
namespace iDomConst
52
{
53
constexpr int MAX_CONNECTION = 10;
54
constexpr int FREE  = 1;
55
constexpr int RS232 = 11;
56
constexpr int CLOCK = 12;
57
constexpr int ok    = 0;
58
constexpr int GPIO_SPIK = 21;
59
constexpr int GPIO_PRINTER = 22;
60
constexpr int BUTTON_PIN = 25;
61
}
62
struct ALERT
63
{
64
    Clock time;
65
    STATE state = STATE::DEACTIVE;
66
    unsigned int fromVolume = 48;
67
    unsigned int toVolume = 58;
68
    unsigned int radioID = 8;
69
};
70
71
extern std::string _logfile;
72
extern Logger log_file_mutex;
73
extern std::string buffer;
74
75
enum class TEMPERATURE_STATE;
76
enum class PILOT_KEY;
77
78
struct MPD_info{
79
    std::string title   = "NULL";
80
    std::string radio   = "NULL";
81
    std::string artist  = "NULL";
82
    int volume = 0;
83
    bool isPlay = false;
84
    int currentSongID = 0;
85
    std::vector <std::string> songList = {"NULL"};
86
};
87
struct s_pointer{
88
    unsigned int *ptr_who;
89
    int32_t *ptr_buf;
90
};
91
92
struct Thread_array_struc {
93
    std::thread thread;
94
    std::thread::id thread_ID = std::thread::id(0);
95
    std::string thread_name;
96
    int thread_socket = 0;
97
};
98
99
struct address_another_servers {
100
    int id;
101
    std::string SERVER_IP;
102
};
103
104
struct FTP_SERVER{
105
    std::string URL;
106
    std::string user;
107
    std::string pass;
108
};
109
struct iDOM_STATE{
110
    STATE houseState = STATE::UNDEFINE;
111
112
};
113
114
struct config{
115
    std::string portRS232;
116
    std::string portRS232_clock;
117
    std::string BaudRate;
118
    std::string RFLinkPort;
119
    std::string RFLinkBaudRate;
120
    int PORT;
121
    std::string SERVER_IP;
122
    std::string MPD_IP;
123
    std::string MOVIES_DB_PATH;
124
    std::string MENU_PATH;
125
    std::string THREAD_MPD   = "NULL";
126
    std::string THREAD_IRDA  = "NULL";
127
    std::string THREAD_CRON  = "NULL";
128
    std::string THREAD_RS232 = "NULL";
129
    std::string THREAD_DUMMY = "NULL";
130
    std::string TS_KEY= " gg ";
131
    std::string cameraLedON = "";
132
    std::string cameraLedOFF ="";
133
    std::string cameraURL="";
134
    std::string facebookAccessToken = "";
135
    std::string viberToken = "NULL";
136
    std::string viberAvatar;
137
    std::vector <std::string> viberReceiver;
138
    std::string viberSender;
139
    std::string radio433MHzConfigFile;
140
    std::string omxplayerFile = "NULL";
141
    int ID_server = 0;
142
    int v_delay;
143
    bool encrypted = true;
144
145
    FTP_SERVER ftpServer;
146
    std::string lightningApiURL = "NULL";
147
    std::string saveFilePath = "NULL";
148
};
149
150
struct LED_Strip{
151
    std::string from;
152
    std::string to;
153
    std::string R;
154
    std::string G;
155
    std::string B;
156
    std::string colorName;
157
158
    LED_Strip (int from, int to, int r, int g, int b, std::string colorName = "NULL"):from(std::to_string(from)),
159
        to(std::to_string(to)),
160
        R(std::to_string(r)),
161
        G(std::to_string(g)),
162
        B(std::to_string(b)),
163
        colorName(colorName)
164
    {
165
166
    }
167
    LED_Strip (const std::string& from,
168
               const std::string& to,
169
               const std::string& r,
170
               const std::string& g,
171
               const std::string& b,
172
               const std::string& colorName = "NULL"):
173
        from(from),
174
        to(to),
175
        R(r),
176
        G(g),
177
        B(b),
178
        colorName(colorName)
179
    {
180
181
    }
182
183
    void set (const std::string& from,
184
              const std::string& to,
185
              const std::string& r,
186
              const std::string& g,
187
              const std::string& b,
188
              const std::string& colorName = "NULL")
189
    {
190
        this->from =from;
191
        this->to = to;
192
        R = r;
193
        G = g;
194
        B = b;
195
        this->colorName =colorName;
196
    }
197
198
    void set (int from, int to, int r, int g, int b, std::string colorName = "NULL"){
199
        this->from = std::to_string(from);
200
        this->to = std::to_string(to);
201
        R = std::to_string(r);
202
        G = std::to_string(g);
203
        B = std::to_string(b);
204
        this->colorName =colorName;
205
    }
206
207
    std::string getColorName() const{
208
        return colorName;
209
    }
210
211
    std::string get(unsigned int _from, unsigned int _to) const{
212
        if (_from != 0 || _to != 60){
213
            return "LED:["+std::to_string(_from)+"-"+std::to_string(_to)+"-"+R+"-"+G+"-"+B+"];";
214
        }
215
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
216
    }
217
218
    std::string makeCommand(const std::string& from,
219
                            const std::string& to,
220
                            const std::string& R,
221
                            const std::string& G,
222
                            const std::string& B){
223
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
224
    }
225
};
226
227
struct pilot_led{
228
    unsigned int counter=0;
229
    std::vector<LED_Strip> colorLED   = { LED_Strip(1,60,237,145,33 ,"carrot orange"),
230
                                          LED_Strip(1,60,255,0,0    ,"red"),
231
                                          LED_Strip(1,60,0,255,0    ,"green"),
232
                                          LED_Strip(1,60,0,0,255    ,"blue"),
233
                                          LED_Strip(1,60,255,255,255,"white"),
234
                                          LED_Strip(1,60,255,255,0  ,"yellow"),
235
                                          LED_Strip(1,60,0,255,255  ,"cyan"),
236
                                          LED_Strip(1,60,255,0,255  ,"magenta")
237
                                        };
238
};
239
240
class command; // for struc thread_data req
241
class iDomTOOLS;
242
class RADIO_EQ_CONTAINER;
243
class RFLinkHandler;
244
245
struct thread_data{
246
    int s_client_sock;
247
    struct sockaddr_in from;
248
    struct config *server_settings = NULL;
249
    struct s_pointer pointer;
250
    LCD_c *mainLCD = NULL;
251
    files_tree *main_tree = NULL;
252
    menu_tree *main_MENU = NULL;
253
    iDomTOOLS *main_iDomTools = NULL;
254
    RFLinkHandler *main_RFLink = NULL;
255
    std::array<Thread_array_struc, iDomConst::MAX_CONNECTION> *main_THREAD_arr = NULL;
256
    time_t start;
257
    time_t now_time;
258
    int sleeper;
259
    std::map <std::string, std::unique_ptr <KEY> > key_map;
260
    MPD_info *ptr_MPD_info = NULL;
261
    pilot_led * ptr_pilot_led = NULL;
262
    std::map <std::string, std::unique_ptr<command> >* commandMapPtr = NULL;
263
    event_counters_handler myEventHandler;
264
    std::string encriptionKey = "40%";
265
    iDomSTATUS *main_iDomStatus;
266
    iDOM_STATE idom_all_state;
267
    ALERT alarmTime;
268
    std::shared_ptr<RADIO_EQ_CONTAINER> main_REC;
269
    iDomStateEnum iDomProgramState = iDomStateEnum::WORKING;
270
};
271
272
struct thread_data_rs232{
273
    std::string portRS232;
274
    std::string portRS232_clock;
275
    std::string BaudRate;
276
    struct s_pointer pointer;
277
};
278
279
#endif // GLOBAL_H
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_ok_BT.cpp
Line
Count
Source
1
#include "../command_ok.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_ok_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_ok_Class_fixture()
8
1
    {
9
1
10
1
    }
11
12
protected:
13
    std::unique_ptr<command_ok> test_command_ok;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
17
1
    {
18
1
        iDomTOOLS_ClassTest::SetUp();
19
1
        test_command_ok =  std::make_unique <command_ok> ("ok");
20
1
    }
21
22
    void TearDown() final
23
1
    {
24
1
        iDomTOOLS_ClassTest::TearDown();
25
1
    }
26
};
27
28
TEST_F(command_ok_Class_fixture, main)
29
1
{
30
1
    test_v.push_back("ok");
31
1
    auto ret = test_command_ok->execute(test_v,&test_my_data);
32
1
    EXPECT_STREQ(ret.c_str(),"\nEND\n");
33
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/433MHz/RFLink/rflinkhandler.h
Line
Count
Source
1
#ifndef RFLINKHANDLER_H
2
#define RFLINKHANDLER_H
3
4
#include <map>
5
#include <exception>
6
#include "../../SerialPi/serialpi.h"
7
#include "../../iDom_server_OOP.h"
8
9
class WRONG_FORMAT : public std::exception{
10
11
};
12
13
struct RFLink_DEV{
14
    int m_counter = 0;
15
    std::string msg;
16
9
    void counter(){
17
9
        ++m_counter;
18
9
    }
19
20
2
    std::string read(){
21
2
        return std::to_string(m_counter) + " \t"+ msg;
22
2
    }
23
};
24
25
class RFLinkHandler
26
{
27
    thread_data *my_data;
28
    SerialPi serial_RFLink;
29
30
public:
31
32
    static std::mutex sm_RFLink_MUTEX;
33
    static std::string sm_RFLink_BUFOR;
34
35
    unsigned int okTime = 0;
36
    unsigned int pingTime = 0;
37
    ////// temporarnie //////
38
    std::map<std::string, RFLink_DEV> rflinkMAP;
39
    /////////////////////////////
40
    RFLinkHandler(thread_data *my_data);
41
42
    bool init();
43
    // void run();
44
    void flush();
45
    void sendCommand(std::string cmd);
46
    std::string sendCommandAndWaitForReceive(std::string cmd);
47
    std::string readFromRS232();
48
private:
49
    std::string internalReadFromRS232();
50
//#ifdef BT_TEST
51
public:
52
//#endif
53
    static std::string getArgumentValueFromRFLinkMSG(const std::string &msg, const std::string &var);
54
};
55
56
#endif // RFLINKHANDLER_H
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_program_BT.cpp
Line
Count
Source
1
#include "../command_program.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_program_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_program_Class_fixture()
8
9
    {
9
9
10
9
    }
11
12
protected:
13
    std::unique_ptr<command_program> test_command_program;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
17
9
    {
18
9
        iDomTOOLS_ClassTest::SetUp();
19
9
        test_command_program = std::make_unique <command_program> ("program");
20
9
    }
21
22
    void TearDown() final
23
9
    {
24
9
        iDomTOOLS_ClassTest::TearDown();
25
9
    }
26
};
27
28
TEST_F(command_program_Class_fixture, unknownParameter)
29
1
{
30
1
    test_v.clear();
31
1
    test_v.push_back("program");
32
1
    test_v.push_back("test");
33
1
    auto ret = test_command_program->execute(test_v,&test_my_data);
34
1
    EXPECT_STREQ(ret.c_str(), "add more paramiters");
35
1
36
1
}
37
38
TEST_F(command_program_Class_fixture, missingParameter)
39
1
{
40
1
    test_v.clear();
41
1
    test_v.push_back("program");
42
1
    auto ret = test_command_program->execute(test_v,&test_my_data);
43
1
    EXPECT_THAT(ret, ::testing::HasSubstr("what?"));
44
1
}
45
46
TEST_F(command_program_Class_fixture, fakeParameter)
47
1
{
48
1
    test_v.clear();
49
1
    test_v.push_back("program");
50
1
    test_v.push_back("fake");
51
1
    test_v.push_back("fake2");
52
1
    auto ret = test_command_program->execute(test_v,&test_my_data);
53
1
    EXPECT_THAT(ret, ::testing::HasSubstr("what? - fake"));
54
1
}
55
56
TEST_F(command_program_Class_fixture, stopProgram)
57
1
{
58
1
    test_v.clear();
59
1
    test_v.push_back("program");
60
1
    test_v.push_back("stop");
61
1
    EXPECT_THROW(test_command_program->execute(test_v,&test_my_data), std::string);
62
1
}
63
64
TEST_F(command_program_Class_fixture, programReloadSoft)
65
1
{
66
1
    test_v.clear();
67
1
    test_v.push_back("program");
68
1
    test_v.push_back("reload");
69
1
    test_v.push_back("soft");
70
1
    EXPECT_THROW(test_command_program->execute(test_v,&test_my_data), std::string);
71
1
    EXPECT_EQ(test_my_data.iDomProgramState, iDomStateEnum::RELOAD);
72
1
}
73
74
TEST_F(command_program_Class_fixture, programReloadHard)
75
1
{
76
1
    test_v.clear();
77
1
    test_v.push_back("program");
78
1
    test_v.push_back("reload");
79
1
    test_v.push_back("hard");
80
1
    EXPECT_THROW(test_command_program->execute(test_v,&test_my_data), std::string);
81
1
    EXPECT_EQ(test_my_data.iDomProgramState, iDomStateEnum::HARD_RELOAD);
82
1
}
83
84
TEST_F(command_program_Class_fixture, clearRamProgram)
85
1
{
86
1
    test_v.clear();
87
1
    test_v.push_back("program");
88
1
    test_v.push_back("clear");
89
1
    test_v.push_back("ram");
90
1
    auto ret = test_command_program->execute(test_v,&test_my_data);
91
1
    EXPECT_STREQ(ret.c_str(),"ram has beed freed");
92
1
}
93
94
TEST_F(command_program_Class_fixture, raspberryProgram)
95
1
{
96
1
    test_v.clear();
97
1
    test_v.push_back("program");
98
1
    test_v.push_back("raspberry");
99
1
    test_v.push_back("command");
100
1
    auto ret = test_command_program->execute(test_v,&test_my_data);
101
1
    EXPECT_STREQ(ret.c_str(),"command done with exitcode: 0");
102
1
}
103
104
TEST_F(command_program_Class_fixture, debugeVariableProgram)
105
1
{
106
1
    RFLinkHandler test_RFLinkkHandler(&test_my_data);
107
1
108
1
    test_my_data.main_RFLink = &test_RFLinkkHandler;
109
1
    test_my_data.main_RFLink->okTime = 777;
110
1
    test_my_data.main_RFLink->pingTime = 888;
111
1
    test_my_data.server_settings->PORT = 88;
112
1
    test_my_data.server_settings->v_delay = 1;
113
1
    test_my_data.sleeper = 1;
114
1
    test_my_data.now_time = 123;
115
1
    test_my_data.start = 12;
116
1
    int32_t buf = 1;
117
1
    unsigned int who = 0;
118
1
    test_my_data.pointer.ptr_buf = &buf;
119
1
    test_my_data.pointer.ptr_who = &who;
120
1
121
1
    test_v.clear();
122
1
    test_v.push_back("program");
123
1
    test_v.push_back("debuge");
124
1
    test_v.push_back("variable");
125
1
    auto ret = test_command_program->execute(test_v,&test_my_data);
126
1
    std::cout << ret << std::endl;
127
1
    EXPECT_THAT(ret,testing::HasSubstr("END"));
128
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/RADIO_433_eq/radio_433_eq.h
Line
Count
Source
1
#ifndef RADIO_SWITCH_H
2
#define RADIO_SWITCH_H
3
#include <gtest/gtest.h>
4
#include <gmock/gmock.h>
5
#include <map>
6
#include "../iDomStatus/idomstatus.h"
7
#include "../433MHz/RFLink/rflinkhandler.h"
8
9
#include "../433MHz/rc_433mhz.h"
10
#include "json.hpp"
11
12
struct WEATHER_STRUCT{
13
private:
14
    unsigned long int m_counter = 0;
15
protected:
16
    unsigned int m_humidity = 0;
17
    double m_temperature = 0.0;
18
    unsigned int m_barometricPressure = 0;
19
public:
20
    unsigned int getHumidity(){ return m_humidity; }
21
    double getTemperature(){ return m_temperature; }
22
    unsigned int getBarometricPressure(){ return m_barometricPressure; }
23
    std::string getDataString(){
24
        return "data: "+std::to_string(m_counter)+"\n"+"Humidity=" + std::to_string(getHumidity()) +"%\n"+
25
                "temperature= " + to_string_with_precision(getTemperature()) + "c\n"+
26
                "Pressure= " + std::to_string(getBarometricPressure())+ "kPa\n";
27
    }
28
29
    void putData(std::string data){
30
        std::string tempStr;
31
        int t = 0;
32
        ++m_counter;
33
        try{
34
            m_humidity = std::stoi( RFLinkHandler::getArgumentValueFromRFLinkMSG(data, "HUM") );
35
        }
36
        catch (...){ }
37
        try{
38
            m_barometricPressure = std::stoi( RFLinkHandler::getArgumentValueFromRFLinkMSG(data, "BARO") );
39
        }
40
        catch (...){ }
41
        try{
42
            tempStr = RFLinkHandler::getArgumentValueFromRFLinkMSG(data, "TEMP");
43
            std::stringstream ss;
44
            ss << std::hex << tempStr.substr(tempStr.size()-3,tempStr.size());
45
            ss >> t;
46
            m_temperature = t / 10.0;
47
            if(tempStr.at(0) == '8'){
48
                m_temperature *= -1.0;
49
            }
50
        }
51
        catch (...){ }
52
        //std::cout << "DUPA: "<<data<<" temp=" << m_temperature<< " hum="<<m_humidity<< std::endl;
53
    }
54
};
55
56
enum class RADIO_EQ_TYPE{
57
    SWITCH = 1,
58
    PIR,
59
    GATE,
60
    BUTTON,
61
    WEATHER_S,
62
    NONE
63
};
64
struct RADIO_EQ_CONFIG{
65
    std::string name = "NULL";
66
    std::string ID   = "NULL";
67
    std::string type = "NULL";
68
    std::string onCode  = "NULL";
69
    std::string offCode = "NULL";
70
    std::string on15sec = "NULL";
71
    std::string sunrise = "NULL";
72
    std::string sunset  = "NULL";
73
    std::string lock   = "NULL";
74
    std::string unlock = "NULL";
75
    void set(std::string type,
76
             std::string name,
77
             std::string ID,
78
             std::string onCode = "null",
79
             std::string offCode = "null",
80
             std::string on15sec = "null",
81
             std::string sunrise = "null",
82
             std::string sunset = "null",
83
             std::string lock = "null",
84
6
             std::string unlock = "null"){
85
6
        this->name = name;
86
6
        this->ID   = ID;
87
6
        this->type = type;
88
6
        this->onCode  = onCode;
89
6
        this->offCode = offCode;
90
6
        this->on15sec = on15sec;
91
6
        this->sunrise = sunrise;
92
6
        this->sunset  = sunset;
93
6
        this->lock   = lock;
94
6
        this->unlock = unlock;
95
6
    }
96
97
    nlohmann::json getJson(){
98
        nlohmann::json jj;
99
        jj["name"]  = name;
100
        jj["id"]    = ID;
101
        jj["type"]  = type;
102
        jj["ON"]    = onCode;
103
        jj["OFF"]   = offCode;
104
        jj["on15sec"] = on15sec;
105
        jj["sunrise"] = sunrise;
106
        jj["sunset"]  = sunset;
107
        jj["lock"]   = lock;
108
        jj["unlock"] = unlock;
109
        return jj;
110
    }
111
};
112
113
class RADIO_EQ{
114
public:
115
    RADIO_EQ();
116
    virtual ~RADIO_EQ();
117
    virtual STATE getState() = 0;
118
    virtual std::string getName() = 0;
119
    virtual std::string getID() = 0;
120
    virtual RADIO_EQ_TYPE getType();
121
protected:
122
    thread_data *m_my_data;
123
    RADIO_EQ_TYPE m_type;
124
public:
125
    RADIO_EQ_CONFIG m_config;
126
};
127
class RADIO_WEATHER_STATION: public RADIO_EQ
128
{
129
    STATE m_state = STATE::UNDEFINE;
130
131
public:
132
    RADIO_WEATHER_STATION(thread_data * my_data, const RADIO_EQ_CONFIG& cfg, RADIO_EQ_TYPE type);
133
    ~RADIO_WEATHER_STATION();
134
    STATE getState();
135
    std::string getName();
136
    std::string getID();
137
    // data
138
    WEATHER_STRUCT data;
139
};
140
class RADIO_BUTTON: public RADIO_EQ
141
{
142
    STATE m_state = STATE::UNDEFINE;
143
144
public:
145
    RADIO_BUTTON(thread_data * my_data, const RADIO_EQ_CONFIG& cfg, RADIO_EQ_TYPE type);
146
    ~RADIO_BUTTON();
147
    STATE getState();
148
    void setState(STATE s);
149
    std::string getName();
150
    std::string getID();
151
};
152
153
class RADIO_SWITCH: public RADIO_EQ
154
{
155
#ifdef BT_TEST
156
public:
157
#endif
158
    RC_433MHz main433MHz;
159
    STATE m_state = STATE::UNDEFINE;
160
public:
161
    RADIO_SWITCH(thread_data * my_data, const RADIO_EQ_CONFIG& cfg, RADIO_EQ_TYPE type);
162
    ~RADIO_SWITCH();
163
    void on();
164
    void off();
165
    void onFor15sec();
166
    void onSunrise();
167
    void onSunset();
168
    void onLockHome();
169
    void onUnlockHome();
170
    STATE getState();
171
    std::string getName();
172
    std::string getID();
173
    void setCode(RADIO_EQ_CONFIG cfg);
174
    STATE m_sunrise = STATE::UNDEFINE;
175
    STATE m_sunset  = STATE::UNDEFINE;
176
};
177
178
class RADIO_EQ_CONTAINER
179
{
180
    std::map <std::string, RADIO_EQ* > m_radioEqMap;
181
    thread_data * my_data;
182
    nlohmann::json m_configJson;
183
public:
184
    RADIO_EQ_CONTAINER(thread_data * my_data);
185
    virtual ~RADIO_EQ_CONTAINER();
186
    void addRadioEq(RADIO_EQ_CONFIG cfg, RADIO_EQ_TYPE type);
187
    void addRadioEq(RADIO_EQ_CONFIG cfg, const std::string& type);
188
    void deleteRadioEq(const std::string &name);
189
    virtual RADIO_EQ* getEqPointer(std::string name);
190
    std::vector<RADIO_SWITCH*> getSwitchPointerVector();
191
    std::vector<RADIO_BUTTON*> getButtonPointerVector();
192
    std::vector<RADIO_WEATHER_STATION *> getWeather_StationPtrVector();
193
    std::string listAllName();
194
    bool nameExist(const std::string &name);
195
    void loadConfig(const std::string &filePath);
196
    void saveConfig(const std::string &filePath);
197
};
198
199
class RADIO_EQ_CONTAINER_STUB : public RADIO_EQ_CONTAINER
200
{
201
    thread_data * k;
202
public:
203
    RADIO_EQ_CONTAINER_STUB(thread_data * k):RADIO_EQ_CONTAINER(k){this->k = k;}
204
205
    virtual ~RADIO_EQ_CONTAINER_STUB(){puts("~RADIO_EQ_CONTAINER_STUB()");}
206
    MOCK_METHOD1(getEqPointer, RADIO_EQ*(std::string name));
207
};
208
209
#endif // RADIO_SWITCH_H
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_put_BT.cpp
Line
Count
Source
1
#include "../command_put.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_put_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_put_Class_fixture()
8
1
    {
9
1
10
1
    }
11
12
protected:
13
    std::unique_ptr<command_put> test_command_put;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
17
1
    {
18
1
        iDomTOOLS_ClassTest::SetUp();
19
1
        test_command_put = std::make_unique <command_put> ("put");
20
1
    }
21
22
    void TearDown() final
23
1
    {
24
1
        iDomTOOLS_ClassTest::TearDown();
25
1
    }
26
};
27
28
TEST_F(command_put_Class_fixture, main)
29
1
{
30
1
    TEST_DATA::return_send_to_arduino = "-2:3";
31
1
32
1
    test_v.push_back("put");
33
1
    test_v.push_back("temperature");
34
1
    auto ret = test_command_put->execute(test_v,&test_my_data);
35
1
    EXPECT_STREQ(ret.c_str(), "DONE");
36
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_433mhz_BT.cpp
Line
Count
Source
1
#include "../command_433mhz.h"
2
#include "../../../functions/functions.h"
3
#include "../../../RADIO_433_eq/radio_433_eq.h"
4
#include "../../../433MHz/RFLink/rflinkhandler.h"
5
#include "../../../iDomTools/test/iDomTools_fixture.h"
6
7
class command433MHz_Class_fixture : public iDomTOOLS_ClassTest
8
{
9
public:
10
    command433MHz_Class_fixture()
11
13
    {
12
13
        this->test_command_433MHz = std::nullptr_t();
13
13
        this->test_RFLink = std::nullptr_t();
14
13
    }
15
16
protected:
17
    std::vector<std::string> test_v= {"433MHz"};
18
    RFLinkHandler* test_RFLink;
19
    blockQueue test_q;
20
    command_433MHz* test_command_433MHz;
21
22
    void SetUp() final
23
13
    {
24
13
        iDomTOOLS_ClassTest::SetUp();
25
13
26
13
        test_q._clearAll();
27
13
28
13
        test_RFLink = new RFLinkHandler(&test_my_data);
29
13
        test_command_433MHz = new command_433MHz("433MHz");
30
13
        test_my_data.main_RFLink = test_RFLink;
31
13
        std::cout << "command433MHz_Class_fixture SetUp" << std::endl;
32
13
    }
33
34
    void TearDown() final
35
13
    {
36
13
        iDomTOOLS_ClassTest::TearDown();
37
13
        delete test_RFLink;
38
13
        delete test_command_433MHz;
39
13
        std::cout << "command433MHz_Class_fixture TearDown" << std::endl;
40
13
    }
41
42
    void addSwitch(const std::string& name)
43
1
    {
44
1
        test_v.clear();
45
1
        test_v.push_back("433MHz");
46
1
        test_v.push_back("add");
47
1
        test_v.push_back("SWITCH");
48
1
        test_v.push_back(name);
49
1
        test_v.push_back("1234");
50
1
        test_v.push_back("onCode_A");
51
1
        test_v.push_back("ofCode_A");
52
1
        test_v.push_back("on15sec_A");
53
1
        test_v.push_back("sunrise_A");
54
1
        test_v.push_back("sunset_A");
55
1
        test_v.push_back("lock_A");
56
1
        test_v.push_back("unlock_A");
57
1
        std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
58
1
    }
59
    void deleteSwitch(const std::string& name)
60
2
    {
61
2
        test_v.clear();
62
2
        test_v.push_back("433MHz");
63
2
        test_v.push_back("delete");
64
2
        test_v.push_back(name);
65
2
        std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
66
2
    }
67
};
68
TEST_F(command433MHz_Class_fixture, getCommandName)
69
1
{
70
1
    EXPECT_THAT(test_command_433MHz->getCommandName(),testing::HasSubstr("433MHz"));
71
1
}
72
73
TEST_F(command433MHz_Class_fixture, deleteSwitch)
74
1
{
75
1
    test_v.push_back("show");
76
1
    test_v.push_back("all");
77
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
78
1
    auto v = test_rec->getSwitchPointerVector();
79
1
    EXPECT_EQ(v.size(),5);
80
1
    test_v.clear();
81
1
    test_v.push_back("433MHz");
82
1
    test_v.push_back("delete");
83
1
    test_v.push_back("A");
84
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
85
1
    v = test_rec->getSwitchPointerVector();
86
1
    EXPECT_EQ(v.size(),4);
87
1
    test_v.clear();
88
1
    test_v.push_back("433MHz");
89
1
    test_v.push_back("show");
90
1
    test_v.push_back("all");
91
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
92
1
    addSwitch("A");
93
1
94
1
}
95
TEST_F(command433MHz_Class_fixture, deleteFakeSwitch)
96
1
{
97
1
    int actualSize = test_rec->getSwitchPointerVector().size();
98
1
    test_v.push_back("show");
99
1
    test_v.push_back("all");
100
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
101
1
    auto v = test_rec->getSwitchPointerVector();
102
1
    EXPECT_EQ(v.size(),actualSize);
103
1
    test_v.clear();
104
1
    test_v.push_back("433MHz");
105
1
    test_v.push_back("delete");
106
1
    test_v.push_back("fake");
107
1
    std::string result = test_command_433MHz->execute(test_v,&test_my_data);
108
1
    EXPECT_THAT(result, testing::HasSubstr("not exist"));
109
1
    v = test_rec->getSwitchPointerVector();
110
1
    EXPECT_EQ(v.size(),actualSize);
111
1
    test_v.clear();
112
1
    test_v.push_back("433MHz");
113
1
    test_v.push_back("show");
114
1
    test_v.push_back("all");
115
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
116
1
}
117
TEST_F(command433MHz_Class_fixture, addButton)
118
1
{
119
1
    int actualSize = test_rec->getButtonPointerVector().size();
120
1
    test_v.push_back("show");
121
1
    test_v.push_back("all");
122
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
123
1
    auto v = test_rec->getButtonPointerVector();
124
1
    EXPECT_EQ(v.size(),actualSize);
125
1
    test_v.clear();
126
1
    test_v.push_back("433MHz");
127
1
    test_v.push_back("add");
128
1
    test_v.push_back("BUTTON");
129
1
    test_v.push_back("glowny");
130
1
    test_v.push_back("4321");
131
1
    test_v.push_back("onCode");
132
1
    test_v.push_back("offCode");
133
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
134
1
    v = test_rec->getButtonPointerVector();
135
1
    EXPECT_EQ(v.size(),actualSize+1);
136
1
    test_v.clear();
137
1
    test_v.push_back("433MHz");
138
1
    test_v.push_back("show");
139
1
    test_v.push_back("all");
140
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
141
1
    deleteSwitch("glowny");
142
1
}
143
144
TEST_F(command433MHz_Class_fixture, addSwitch)
145
1
{
146
1
    int actualSize = test_rec->getSwitchPointerVector().size();
147
1
    test_v.push_back("show");
148
1
    test_v.push_back("all");
149
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
150
1
    auto v = test_rec->getSwitchPointerVector();
151
1
    EXPECT_EQ(v.size(),actualSize);
152
1
    test_v.clear();
153
1
    test_v.push_back("433MHz");
154
1
    test_v.push_back("add");
155
1
    test_v.push_back("SWITCH");
156
1
    test_v.push_back("Aaa");
157
1
    test_v.push_back("1234");
158
1
    test_v.push_back("onCode_A");
159
1
    test_v.push_back("ofCode_A");
160
1
    test_v.push_back("on15sec_A");
161
1
    test_v.push_back("sunrise_A");
162
1
    test_v.push_back("sunset_A");
163
1
    test_v.push_back("lock_A");
164
1
    test_v.push_back("unlock_A");
165
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
166
1
    v = test_rec->getSwitchPointerVector();
167
1
    EXPECT_EQ(v.size(),actualSize+1);
168
1
    test_v.clear();
169
1
    test_v.push_back("433MHz");
170
1
    test_v.push_back("show");
171
1
    test_v.push_back("all");
172
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
173
1
    deleteSwitch("Aaa");
174
1
}
175
176
TEST_F(command433MHz_Class_fixture, addExistingWeather)
177
1
{
178
1
    test_v.push_back("show");
179
1
    test_v.push_back("all");
180
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
181
1
    auto v = test_rec->getWeather_StationPtrVector();
182
1
    EXPECT_EQ(v.size(),1);
183
1
    test_v.clear();
184
1
    test_v.push_back("433MHz");
185
1
    test_v.push_back("add");
186
1
    test_v.push_back("WEATHER");
187
1
    test_v.push_back("first");
188
1
    test_v.push_back("1234");
189
1
190
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
191
1
    v = test_rec->getWeather_StationPtrVector();
192
1
    EXPECT_EQ(v.size(),1);
193
1
    test_v.clear();
194
1
    test_v.push_back("433MHz");
195
1
    test_v.push_back("show");
196
1
    test_v.push_back("all");
197
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
198
1
}
199
200
TEST_F(command433MHz_Class_fixture, missingParamiter_addSwitch)
201
1
{
202
1
    test_v.push_back("show");
203
1
    test_v.push_back("all");
204
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
205
1
    auto v = test_rec->getSwitchPointerVector();
206
1
    EXPECT_EQ(v.size(),5);
207
1
    test_v.clear();
208
1
    test_v.push_back("433MHz");
209
1
    test_v.push_back("add");
210
1
    test_v.push_back("SWITCH");
211
1
    test_v.push_back("Abc");
212
1
    test_v.push_back("1234");
213
1
    test_v.push_back("onCode_A");
214
1
    test_v.push_back("ofCode_A");
215
1
    test_v.push_back("on15sec_A");
216
1
    std::string result = test_command_433MHz->execute(test_v,&test_my_data);
217
3
    EXPECT_THAT(result, testing::HasSubstr("mising paramiter")) << "nie ma bledu";
218
1
    v = test_rec->getSwitchPointerVector();
219
1
    EXPECT_EQ(v.size(),5);
220
1
    test_v.clear();
221
1
    test_v.push_back("433MHz");
222
1
    test_v.push_back("show");
223
1
    test_v.push_back("all");
224
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
225
1
}
226
\
227
TEST_F(command433MHz_Class_fixture, add_wrongType_addSwitch)
228
1
{
229
1
    test_v.push_back("show");
230
1
    test_v.push_back("all");
231
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
232
1
    auto v = test_rec->getSwitchPointerVector();
233
1
    EXPECT_EQ(v.size(),5);
234
1
    test_v.clear();
235
1
    test_v.push_back("433MHz");
236
1
    test_v.push_back("add");
237
1
    test_v.push_back("FAKE"); //here is wrong type
238
1
    test_v.push_back("Abc");
239
1
    test_v.push_back("1234");
240
1
    test_v.push_back("onCode_A");
241
1
    test_v.push_back("ofCode_A");
242
1
    test_v.push_back("on15sec_A");
243
1
    test_v.push_back("sunrise_A");
244
1
    test_v.push_back("sunset_A");
245
1
    test_v.push_back("lock_A");
246
1
    test_v.push_back("unlock_A");
247
1
    std::string result = test_command_433MHz->execute(test_v,&test_my_data);
248
1
    EXPECT_THAT(result, testing::HasSubstr("wrong type"));
249
1
    std::cout << "wynik testu: " << result << std::endl;
250
1
    v = test_rec->getSwitchPointerVector();
251
1
    EXPECT_EQ(v.size(),5);
252
1
    test_v.clear();
253
1
    test_v.push_back("433MHz");
254
1
    test_v.push_back("show");
255
1
    test_v.push_back("all");
256
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
257
1
}
258
259
TEST_F(command433MHz_Class_fixture, add_wrongID_addSwitch)
260
1
{
261
1
    test_v.push_back("show");
262
1
    test_v.push_back("all");
263
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
264
1
    auto v = test_rec->getSwitchPointerVector();
265
1
    EXPECT_EQ(v.size(),5);
266
1
    test_v.clear();
267
1
    test_v.push_back("433MHz");
268
1
    test_v.push_back("add");
269
1
    test_v.push_back("SWITCH");
270
1
    test_v.push_back("Abc");
271
1
    test_v.push_back("dummy"); //here is wrong ID
272
1
    test_v.push_back("onCode_A");
273
1
    test_v.push_back("ofCode_A");
274
1
    test_v.push_back("on15sec_A");
275
1
    test_v.push_back("sunrise_A");
276
1
    test_v.push_back("sunset_A");
277
1
    test_v.push_back("lock_A");
278
1
    test_v.push_back("unlock_A");
279
1
    std::string result = test_command_433MHz->execute(test_v,&test_my_data);
280
1
    std::cout << "wynik testu: " << result << std::endl;
281
1
    EXPECT_THAT(result, testing::HasSubstr("wrong ID"));
282
1
    v = test_rec->getSwitchPointerVector();
283
1
    EXPECT_EQ(v.size(),5);
284
1
    test_v.clear();
285
1
    test_v.push_back("433MHz");
286
1
    test_v.push_back("show");
287
1
    test_v.push_back("all");
288
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
289
1
}
290
291
TEST_F(command433MHz_Class_fixture, show_switch)
292
1
{
293
1
    test_v.push_back("show");
294
1
    test_v.push_back("all");
295
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
296
1
    auto v = test_rec->getSwitchPointerVector();
297
1
    EXPECT_EQ(v.size(),5);
298
1
    test_v.clear();
299
1
    test_v.push_back("433MHz");
300
1
    test_v.push_back("show");
301
1
    test_v.push_back("switch");
302
1
303
1
    std::string result = test_command_433MHz->execute(test_v,&test_my_data);
304
1
    std::cout << "wynik testu: " << result << std::endl;
305
1
    EXPECT_THAT(result, testing::HasSubstr("UNDEFINE"));
306
1
    v = test_rec->getSwitchPointerVector();
307
1
    EXPECT_EQ(v.size(),5);
308
1
    test_v.clear();
309
1
    test_v.push_back("433MHz");
310
1
    test_v.push_back("show");
311
1
    test_v.push_back("all");
312
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
313
1
}
314
315
TEST_F(command433MHz_Class_fixture, show_aether)
316
1
{
317
1
    test_my_data.main_RFLink->rflinkMAP["kk"].msg = "astro";
318
1
    test_my_data.main_RFLink->rflinkMAP["kk"].m_counter = 99;
319
1
    test_my_data.main_RFLink->rflinkMAP["jj"].msg = "lock";
320
1
    test_my_data.main_RFLink->rflinkMAP["jj"].m_counter = 155;
321
1
    test_v.push_back("show");
322
1
    test_v.push_back("all");
323
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
324
1
    auto v = test_rec->getSwitchPointerVector();
325
1
    EXPECT_EQ(v.size(),5);
326
1
    test_v.clear();
327
1
    test_v.push_back("433MHz");
328
1
    test_v.push_back("show");
329
1
    test_v.push_back("aether");
330
1
331
1
    std::string result = test_command_433MHz->execute(test_v,&test_my_data);
332
1
    std::cout << "wynik testu: " << result << std::endl;
333
1
    EXPECT_THAT(result, testing::HasSubstr("astro"));
334
1
    EXPECT_THAT(result, testing::HasSubstr("lock"));
335
1
    EXPECT_THAT(result, testing::HasSubstr("99"));
336
1
    EXPECT_THAT(result, testing::HasSubstr("155"));
337
1
    v = test_rec->getSwitchPointerVector();
338
1
    EXPECT_EQ(v.size(),5);
339
1
    test_v.clear();
340
1
}
341
342
TEST_F(command433MHz_Class_fixture, switchRF433)
343
1
{
344
1
    test_v.push_back("show");
345
1
    test_v.push_back("all");
346
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
347
1
    auto v = test_rec->getSwitchPointerVector();
348
1
    EXPECT_EQ(v.size(),5);
349
1
    /////////////////////////////// ON
350
1
    test_v.clear();
351
1
    test_v.push_back("433MHz");
352
1
    test_v.push_back("switch");
353
1
    test_v.push_back("B");
354
1
    test_v.push_back("ON");
355
1
    test_command_433MHz->execute(test_v,&test_my_data);
356
1
    EXPECT_EQ(test_my_data.main_REC->getEqPointer("B")->getState(), STATE::ON);
357
1
    ////////////////////////////// OFF
358
1
    test_v.clear();
359
1
    test_v.push_back("433MHz");
360
1
    test_v.push_back("switch");
361
1
    test_v.push_back("B");
362
1
    test_v.push_back("OFF");
363
1
    test_command_433MHz->execute(test_v,&test_my_data);
364
1
    EXPECT_EQ(test_my_data.main_REC->getEqPointer("B")->getState(), STATE::OFF);
365
1
    ////////////////////////////// 15s
366
1
    test_v.clear();
367
1
    test_v.push_back("433MHz");
368
1
    test_v.push_back("switch");
369
1
    test_v.push_back("B");
370
1
    test_v.push_back("15s");
371
1
    test_command_433MHz->execute(test_v,&test_my_data);
372
1
    EXPECT_EQ(test_my_data.main_REC->getEqPointer("B")->getState(), STATE::WORKING);
373
1
    ////////////////////////////// unknown paramiter
374
1
    test_v.clear();
375
1
    test_v.push_back("433MHz");
376
1
    test_v.push_back("switch");
377
1
    test_v.push_back("B");
378
1
    test_v.push_back("fake");
379
1
    std::string result = test_command_433MHz->execute(test_v,&test_my_data);
380
1
    EXPECT_EQ(test_my_data.main_REC->getEqPointer("B")->getState(), STATE::WORKING);
381
1
    EXPECT_THAT(result, testing::HasSubstr("fake"));
382
1
    ///////////////////////////// fake switch
383
1
    test_v.clear();
384
1
    test_v.push_back("433MHz");
385
1
    test_v.push_back("switch");
386
1
    test_v.push_back("B_fake");
387
1
    test_v.push_back("fake");
388
1
389
1
    result = test_command_433MHz->execute(test_v,&test_my_data);
390
1
    EXPECT_THAT(result, testing::HasSubstr("not found"));
391
1
    v = test_rec->getSwitchPointerVector();
392
1
    EXPECT_EQ(v.size(),5);
393
1
    test_v.clear();
394
1
}
395
396
TEST_F(command433MHz_Class_fixture, sendRF433)
397
1
{
398
1
    test_v.push_back("show");
399
1
    test_v.push_back("all");
400
1
    std::cout << test_command_433MHz->execute(test_v,&test_my_data) <<std::endl;
401
1
    auto v = test_rec->getSwitchPointerVector();
402
1
    EXPECT_EQ(v.size(),5);
403
1
    test_v.clear();
404
1
    test_v.push_back("433MHz");
405
1
    test_v.push_back("send");
406
1
    test_v.push_back("fake");
407
1
408
1
     std::string retStr = test_command_433MHz->execute(test_v,&test_my_data);
409
    EXPECT_THAT(retStr, testing::HasSubstr("sended"));
410
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_rs232_BT.cpp
Line
Count
Source
1
#include "../commandrs232.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_RS232_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_RS232_Class_fixture()
8
8
    {
9
8
10
8
    }
11
12
protected:
13
    std::unique_ptr<commandRS232> test_command_put;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
17
8
    {
18
8
        iDomTOOLS_ClassTest::SetUp();
19
8
        test_command_put = std::make_unique <commandRS232> ("RS232");
20
8
    }
21
22
    void TearDown() final
23
8
    {
24
8
        iDomTOOLS_ClassTest::TearDown();
25
8
    }
26
};
27
28
TEST_F(command_RS232_Class_fixture, wrongParameter)
29
1
{
30
1
    test_v.push_back("RS232");
31
1
    test_v.push_back("test_par");
32
1
    auto ret = test_command_put->execute(test_v,&test_my_data);
33
1
    EXPECT_STREQ(ret.c_str(), "wrong parameter: test_par");
34
1
}
35
36
TEST_F(command_RS232_Class_fixture, getWrongParameter)
37
1
{
38
1
    test_v.push_back("RS232");
39
1
    test_v.push_back("get");
40
1
    test_v.push_back("fake");
41
1
    auto ret = test_command_put->execute(test_v,&test_my_data);
42
1
    EXPECT_STREQ(ret.c_str(), "wrong parameter: fake");
43
1
}
44
45
TEST_F(command_RS232_Class_fixture, getTemperature)
46
1
{
47
1
    TEST_DATA::return_send_to_arduino = "-2:-21";
48
1
49
1
    test_v.push_back("RS232");
50
1
    test_v.push_back("get");
51
1
    test_v.push_back("temperature");
52
1
    auto ret = test_command_put->execute(test_v,&test_my_data);
53
1
    EXPECT_THAT(ret, ::testing::HasSubstr("-2:-21"));
54
1
}
55
56
TEST_F(command_RS232_Class_fixture, send)
57
1
{
58
1
    TEST_DATA::return_send_to_arduino = "done";
59
1
60
1
    test_v.push_back("RS232");
61
1
    test_v.push_back("send");
62
1
    test_v.push_back("test:33;");
63
1
    auto ret = test_command_put->execute(test_v,&test_my_data);
64
1
    EXPECT_STREQ(ret.c_str(), "done");
65
1
}
66
67
TEST_F(command_RS232_Class_fixture, errorMissingPara)
68
1
{
69
1
    TEST_DATA::return_send_to_arduino = "done";
70
1
71
1
    test_v.push_back("RS232");
72
1
    test_v.push_back("error");
73
1
    auto ret = test_command_put->execute(test_v,&test_my_data);
74
1
    EXPECT_STREQ(ret.c_str(), "add more parameter to error");
75
1
}
76
77
TEST_F(command_RS232_Class_fixture, errorTemperatureMissingPara)
78
1
{
79
1
    TEST_DATA::return_send_to_arduino = "done";
80
1
81
1
    test_v.push_back("RS232");
82
1
    test_v.push_back("error");
83
1
    test_v.push_back("Temperature");
84
1
    test_v.push_back("error");
85
1
    auto ret = test_command_put->execute(test_v,&test_my_data);
86
1
    EXPECT_STREQ(ret.c_str(), "default");
87
1
}
88
89
TEST_F(command_RS232_Class_fixture, msgTestMissing)
90
1
{
91
1
    TEST_DATA::return_send_to_arduino = "done";
92
1
93
1
    test_v.push_back("RS232");
94
1
    test_v.push_back("error");
95
1
    test_v.push_back("test");
96
1
    test_v.push_back("msg");
97
1
98
1
    test_v.push_back("fake msg");
99
1
100
1
    auto ret = test_command_put->execute(test_v,&test_my_data);
101
1
    EXPECT_STREQ(ret.c_str(), "DONE!");
102
1
}
103
104
TEST_F(command_RS232_Class_fixture, msgTestFake)
105
1
{
106
1
    TEST_DATA::return_send_to_arduino = "done";
107
1
108
1
    test_v.push_back("RS232");
109
1
    test_v.push_back("error");
110
1
    test_v.push_back("test");
111
1
    test_v.push_back("fake");;
112
1
113
1
    auto ret = test_command_put->execute(test_v,&test_my_data);
114
1
    EXPECT_STREQ(ret.c_str(), "default");
115
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_ardu_BT.cpp
Line
Count
Source
1
#include <gtest/gtest.h>
2
#include "../command_ardu.h"
3
#include "../../../functions/functions.h"
4
#include "../../../RADIO_433_eq/radio_433_eq.h"
5
#include "../../../433MHz/RFLink/rflinkhandler.h"
6
#include "../../../iDomTools/test/iDomTools_fixture.h"
7
8
class commandArdu_Class_fixture : public iDomTOOLS_ClassTest
9
{
10
public:
11
11
    commandArdu_Class_fixture() {
12
11
        this->test_RFLink = std::nullptr_t();
13
11
        this->test_ardu = std::nullptr_t();
14
11
    }
15
16
protected:
17
    std::vector<std::string> test_v= {"ardu"};
18
    RFLinkHandler* test_RFLink;
19
    blockQueue test_q;
20
    command_ardu* test_ardu;
21
    void SetUp() final
22
11
    {
23
11
        iDomTOOLS_ClassTest::SetUp();
24
11
25
11
        test_q._clearAll();
26
11
27
11
        test_RFLink = new RFLinkHandler(&test_my_data);
28
11
        test_ardu = new command_ardu("ardu", &test_my_data);
29
11
        test_my_data.main_RFLink = test_RFLink;
30
11
        test_v.push_back("433MHz");
31
11
        std::cout << "commandArdu_Class_fixture SetUp" << std::endl;
32
11
    }
33
34
    void TearDown() final
35
11
    {
36
11
        iDomTOOLS_ClassTest::TearDown();
37
11
        delete test_RFLink;
38
11
        delete test_ardu;
39
11
        std::cout << "commandArdu_Class_fixture TearDown" << std::endl;
40
11
    }
41
42
};
43
44
TEST_F(commandArdu_Class_fixture, wrongMSGformat)
45
1
{
46
1
    test_v.push_back("EV1527;ID=01e7be;SWITCH=01;CMD=ON;"); // wronh msg format missing 20;
47
1
    EXPECT_THROW(test_ardu->execute(test_v, &test_my_data), WRONG_FORMAT);
48
1
}
49
50
TEST_F(commandArdu_Class_fixture, UnlockHome)
51
1
{
52
1
    test_idomTOOLS->lockHome();
53
1
    EXPECT_EQ(test_status.getObjectState("house"),STATE::LOCK);
54
1
55
1
    test_v.push_back("20;EV1527;ID=01e7be;SWITCH=01;CMD=ON;");
56
1
    test_ardu->execute(test_v, &test_my_data);
57
1
    EXPECT_EQ(test_status.getObjectState("house"),STATE::UNLOCK);
58
1
59
1
    EXPECT_EQ(test_q._size(),1);
60
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::PLAY);
61
1
    EXPECT_EQ(test_q._size(),0);
62
1
}
63
64
TEST_F(commandArdu_Class_fixture, LockHome)
65
1
{
66
1
    test_idomTOOLS->unlockHome();
67
1
    EXPECT_EQ(test_status.getObjectState("house"),STATE::UNLOCK);
68
1
69
1
    test_v.push_back("20;EV1527;ID=01e7be;SWITCH=01;CMD=ON;");
70
4
    for(auto i = 0; i < 3; ++i){
71
3
        test_ardu->execute(test_v, &test_my_data);
72
3
    }
73
1
74
1
    EXPECT_EQ(test_status.getObjectState("house"),STATE::LOCK);
75
1
    EXPECT_EQ(test_q._size(),1);
76
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::STOP);
77
1
    EXPECT_EQ(test_q._size(),0);
78
1
}
79
80
TEST_F(commandArdu_Class_fixture, playMusic)
81
1
{
82
1
    test_idomTOOLS->unlockHome();
83
1
    EXPECT_EQ(test_status.getObjectState("house"),STATE::UNLOCK);
84
1
    EXPECT_EQ(test_status.getObjectState("listwa"),STATE::UNKNOWN);
85
1
    test_status.addObject("music",STATE::STOP);
86
1
87
1
    test_v.push_back("20;EV1527;ID=01e7be;SWITCH=01;CMD=ON;");
88
1
89
1
    test_ardu->execute(test_v, &test_my_data);
90
1
91
1
    EXPECT_EQ(test_q._size(),1);
92
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::PLAY);
93
1
    EXPECT_EQ(test_q._size(),0);
94
1
    EXPECT_EQ(test_status.getObjectState("listwa"),STATE::ON);
95
1
}
96
97
TEST_F(commandArdu_Class_fixture, stopMusic)
98
1
{
99
1
    test_idomTOOLS->unlockHome();
100
1
    EXPECT_EQ(test_status.getObjectState("house"),STATE::UNLOCK);
101
1
    EXPECT_EQ(test_status.getObjectState("listwa"),STATE::UNKNOWN);
102
1
    test_status.addObject("music",STATE::PLAY);
103
1
104
1
    test_v.push_back("20;EV1527;ID=01e7be;SWITCH=01;CMD=ON;");
105
1
106
1
    test_ardu->execute(test_v, &test_my_data);
107
1
108
1
    EXPECT_EQ(test_q._size(),1);
109
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::STOP);
110
1
    EXPECT_EQ(test_q._size(),0);
111
1
    EXPECT_EQ(test_status.getObjectState("listwa"),STATE::OFF);
112
1
}
113
114
TEST_F(commandArdu_Class_fixture, weatherStationTemp)
115
1
{
116
1
    test_v.push_back("20;2A;LaCrosse;ID=0704;TEMP=8043;");
117
1
    test_ardu->execute(test_v, &test_my_data);
118
1
    RADIO_WEATHER_STATION* st = static_cast<RADIO_WEATHER_STATION*>(test_my_data.main_REC->getEqPointer("first"));
119
1
    EXPECT_DOUBLE_EQ(-6.7, st->data.getTemperature() );
120
1
    EXPECT_DOUBLE_EQ(0, st->data.getHumidity() );
121
1
    test_v[2] = "20;35;LaCrosse;ID=0704;HUM=42;";
122
1
    test_ardu->execute(test_v, &test_my_data);
123
1
    EXPECT_DOUBLE_EQ(42, st->data.getHumidity() );
124
1
    test_v[2] = "20;2A;LaCrosse;ID=0704;TEMP=0000;";
125
1
    test_ardu->execute(test_v, &test_my_data);
126
1
    EXPECT_DOUBLE_EQ(0, st->data.getTemperature() );
127
1
}
128
129
TEST_F(commandArdu_Class_fixture, command_ardu_show)
130
1
{
131
1
    test_v.pop_back();
132
1
    test_v.push_back("show");
133
1
    std::string retStr = test_ardu->execute(test_v, &test_my_data);
134
1
    EXPECT_THAT(retStr, testing::HasSubstr("data: 0"));
135
1
    EXPECT_THAT(retStr, testing::HasSubstr("temperature= 0c"));
136
1
}
137
138
TEST_F(commandArdu_Class_fixture, command_ardu_help)
139
1
{
140
1
    command_ardu test_Command_ardu ("ardu");
141
1
142
1
    std::string retStr = test_Command_ardu.help();
143
1
    EXPECT_STREQ(retStr.c_str(), " only for internal usege\n");
144
1
}
145
146
TEST_F(commandArdu_Class_fixture, command_ardu_433MHz_throw)
147
1
{
148
1
    test_v.push_back("fake_msg");
149
1
    std::string retStr = test_ardu->execute(test_v, &test_my_data);
150
1
151
1
    EXPECT_THAT(retStr, testing::HasSubstr("for"));
152
1
}
153
154
TEST_F(commandArdu_Class_fixture, command_ardu_433MHz_OK)
155
1
{
156
1
    test_v.push_back("20;53;OK;");
157
1
    test_ardu->execute(test_v, &test_my_data);
158
1
    EXPECT_NE(test_my_data.main_RFLink->okTime, 0);
159
1
    EXPECT_EQ(test_my_data.main_RFLink->okTime, Clock::getUnixTime());
160
1
}
161
162
TEST_F(commandArdu_Class_fixture, command_ardu_433MHz_PING)
163
1
{
164
1
    test_v.push_back("20;99;PONG;");
165
1
    test_ardu->execute(test_v, &test_my_data);
166
1
    EXPECT_NE(test_my_data.main_RFLink->pingTime, 0);
167
    EXPECT_EQ(test_my_data.main_RFLink->pingTime, Clock::getUnixTime());
168
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_big_BT.cpp
Line
Count
Source
1
#include "../command_big.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_big_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_big_Class_fixture()
8
1
    {
9
1
10
1
    }
11
12
protected:
13
    std::unique_ptr<command_big> test_command_big;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
17
1
    {
18
1
        iDomTOOLS_ClassTest::SetUp();
19
1
        test_command_big = std::make_unique <command_big> ("big");
20
1
    }
21
22
    void TearDown() final
23
1
    {
24
1
        iDomTOOLS_ClassTest::TearDown();
25
1
    }
26
};
27
28
TEST_F(command_big_Class_fixture, main)
29
1
{
30
1
    int s = 55;
31
1
    test_v.push_back("big");
32
1
    test_v.push_back(std::to_string(s));
33
1
    auto ret = test_command_big->execute(test_v,&test_my_data);
34
    EXPECT_EQ(ret.size(),s);
35
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_clock_BT.cpp
Line
Count
Source
1
#include "../command_clock.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_clock_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_clock_Class_fixture()
8
2
    {
9
2
10
2
    }
11
12
protected:
13
    std::unique_ptr<command_clock> test_command_clock;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
17
2
    {
18
2
        iDomTOOLS_ClassTest::SetUp();
19
2
        test_command_clock = std::make_unique <command_clock> ("clock");
20
2
    }
21
22
    void TearDown() final
23
2
    {
24
2
        iDomTOOLS_ClassTest::TearDown();
25
2
    }
26
};
27
28
TEST_F(command_clock_Class_fixture, main)
29
1
{
30
1
    test_v.push_back("clock");
31
1
    test_v.push_back("1234");
32
1
    auto ret = test_command_clock->execute(test_v,&test_my_data);
33
1
    EXPECT_STREQ(ret.c_str(),"clock set return test");
34
1
}
35
36
TEST_F(command_clock_Class_fixture, missingParamiter)
37
1
{
38
1
    test_v.push_back("clock");
39
1
    auto ret = test_command_clock->execute(test_v,&test_my_data);
40
    EXPECT_STREQ(ret.c_str(),"can not set clock");
41
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_cmd_BT.cpp
Line
Count
Source
1
#include "../command_cmd.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_cmd_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_cmd_Class_fixture()
8
2
    {
9
2
10
2
    }
11
12
protected:
13
    std::unique_ptr<command_cmd> test_command_cmd;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
17
2
    {
18
2
        iDomTOOLS_ClassTest::SetUp();
19
2
        test_command_cmd = std::make_unique <command_cmd> ("cmd");
20
2
    }
21
22
    void TearDown() final
23
2
    {
24
2
        iDomTOOLS_ClassTest::TearDown();
25
2
    }
26
};
27
28
TEST_F(command_cmd_Class_fixture, main)
29
1
{
30
1
    test_my_data.server_settings->omxplayerFile = "/mnt/ramdisk/cmd";
31
1
    test_v.push_back("cmd");
32
1
    auto ret = test_command_cmd->execute(test_v,&test_my_data);
33
1
    EXPECT_THAT(ret, ::testing::HasSubstr("fifo file contain:"));
34
1
}
35
36
TEST_F(command_cmd_Class_fixture, wrongParamiter)
37
1
{
38
1
    test_v.push_back("cmd");
39
1
    test_v.push_back("1234");
40
1
    auto ret = test_command_cmd->execute(test_v,&test_my_data);
41
    EXPECT_STREQ(ret.c_str(),"error: unknown parameter: 1234");
42
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_event_BT.cpp
Line
Count
Source
1
#include "../command_event.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_event_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_event_Class_fixture()
8
6
    {
9
6
10
6
    }
11
12
protected:
13
    std::unique_ptr<command_event> test_command_event;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
17
6
    {
18
6
        iDomTOOLS_ClassTest::SetUp();
19
6
        test_command_event = std::make_unique <command_event> ("event");
20
6
    }
21
22
    void TearDown() final
23
6
    {
24
6
        iDomTOOLS_ClassTest::TearDown();
25
6
    }
26
};
27
28
TEST_F(command_event_Class_fixture, eventList)
29
1
{
30
1
    test_v.push_back("event");
31
1
    auto ret = test_command_event->execute(test_v,&test_my_data);
32
1
    EXPECT_THAT(ret, ::testing::HasSubstr("pilot"));
33
1
}
34
35
TEST_F(command_event_Class_fixture, eventPilot)
36
1
{
37
1
    test_v.push_back("event");
38
1
    test_v.push_back("pilot");
39
1
    auto ret = test_command_event->execute(test_v,&test_my_data);
40
1
    EXPECT_THAT(ret, ::testing::HasSubstr("pilot"));
41
1
}
42
43
TEST_F(command_event_Class_fixture, clearEventPilot)
44
1
{
45
1
    test_my_data.myEventHandler.run("pilot")->addEvent("pilot test");
46
1
    EXPECT_EQ(test_my_data.myEventHandler.run("pilot")->howManyEvent(),1);
47
1
    test_v.push_back("event");
48
1
    test_v.push_back("pilot");
49
1
    test_v.push_back("clear");
50
1
    test_command_event->execute(test_v,&test_my_data);
51
1
    EXPECT_EQ(test_my_data.myEventHandler.run("pilot")->howManyEvent(),0);
52
1
}
53
54
TEST_F(command_event_Class_fixture, clearsSomeEventPilot)
55
1
{
56
11
    for(int i = 0; i<10; ++i){
57
10
    test_my_data.myEventHandler.run("pilot")->addEvent("pilot test");
58
10
    }
59
1
    EXPECT_EQ(test_my_data.myEventHandler.run("pilot")->howManyEvent(),10);
60
1
    test_v.push_back("event");
61
1
    test_v.push_back("pilot");
62
1
    test_v.push_back("clear");
63
1
    test_v.push_back("3");
64
1
    test_v.push_back("6");
65
1
    test_command_event->execute(test_v,&test_my_data);
66
1
    EXPECT_EQ(test_my_data.myEventHandler.run("pilot")->howManyEvent(),7);
67
1
}
68
69
TEST_F(command_event_Class_fixture, intensityEventPilot)
70
1
{
71
1
    test_my_data.myEventHandler.run("pilot")->addEvent("pilot test");
72
1
    EXPECT_EQ(test_my_data.myEventHandler.run("pilot")->howManyEvent(),1);
73
1
    test_v.push_back("event");
74
1
    test_v.push_back("pilot");
75
1
    test_v.push_back("intensity");
76
1
    auto ret = test_command_event->execute(test_v,&test_my_data);
77
1
    EXPECT_STREQ(ret.c_str(),"event pilot 1 intensity per last minute!");
78
1
    EXPECT_EQ(test_my_data.myEventHandler.run("pilot")->howManyEvent(),1);
79
1
}
80
81
TEST_F(command_event_Class_fixture, wrongParamiter)
82
1
{
83
1
    test_v.push_back("event");
84
1
    test_v.push_back("pilot");
85
1
    test_v.push_back("clear");
86
1
    test_v.push_back("3");
87
1
    test_v.push_back("6");
88
1
    test_v.push_back("clear");
89
1
    test_v.push_back("3");
90
1
    test_v.push_back("6");
91
1
    test_v.push_back("clear");
92
1
    test_v.push_back("3");
93
1
    test_v.push_back("6");
94
1
    auto ret = test_command_event->execute(test_v,&test_my_data);
95
    EXPECT_THAT(ret,::testing::HasSubstr("event"));
96
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_exit_BT.cpp
Line
Count
Source
1
#include "../commandexit.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_exit_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_exit_Class_fixture()
8
1
    {
9
1
10
1
    }
11
12
protected:
13
    std::unique_ptr<commandEXIT> test_command_exit;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
17
1
    {
18
1
        iDomTOOLS_ClassTest::SetUp();
19
1
        test_command_exit = std::make_unique <commandEXIT> ("exit");
20
1
    }
21
22
    void TearDown() final
23
1
    {
24
1
        iDomTOOLS_ClassTest::TearDown();
25
1
    }
26
};
27
28
TEST_F(command_exit_Class_fixture, main)
29
1
{
30
1
    test_v.push_back("exit");
31
1
    auto ret = test_command_exit->execute(test_v,&test_my_data);
32
    EXPECT_STREQ(ret.c_str(),"\nEND.\n");
33
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_hello_BT.cpp
Line
Count
Source
1
#include "../command_hello.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_hello_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_hello_Class_fixture()
8
1
    {
9
1
10
1
    }
11
12
protected:
13
    std::unique_ptr<command_hello> test_command_hello;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
17
1
    {
18
1
        iDomTOOLS_ClassTest::SetUp();
19
1
        test_command_hello = std::make_unique <command_hello> ("hello");
20
1
    }
21
22
    void TearDown() final
23
1
    {
24
1
        iDomTOOLS_ClassTest::TearDown();
25
1
    }
26
};
27
28
TEST_F(command_hello_Class_fixture, main)
29
1
{
30
1
    test_v.push_back("hello");
31
1
    auto ret = test_command_hello->execute(test_v,&test_my_data);
32
    EXPECT_STREQ(ret.c_str(),"\nHI You User!\n");
33
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_help_BT.cpp
Line
Count
Source
1
#include "../command_help.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_help_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_help_Class_fixture()
8
3
    {
9
3
10
3
    }
11
12
protected:
13
    std::unique_ptr<command_help> test_command_help;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
17
3
    {
18
3
        iDomTOOLS_ClassTest::SetUp();
19
3
        test_command_help = std::make_unique <command_help> ("help");
20
3
    }
21
22
    void TearDown() final
23
3
    {
24
3
        iDomTOOLS_ClassTest::TearDown();
25
3
    }
26
};
27
28
TEST_F(command_help_Class_fixture, all)
29
1
{
30
1
    std::unique_ptr<commandHandlerRoot> chr = std::make_unique<commandHandlerRoot>(&test_my_data);
31
1
    test_v.push_back("help");
32
1
    auto size = test_command_help->execute(test_v,&test_my_data).size();
33
1
    EXPECT_EQ(size,4376);
34
1
}
35
36
TEST_F(command_help_Class_fixture, one)
37
1
{
38
1
    std::unique_ptr<commandHandlerRoot> chr = std::make_unique<commandHandlerRoot>(&test_my_data);
39
1
    test_v.push_back("help");
40
1
    test_v.push_back("ok");
41
1
    auto ret = test_command_help->execute(test_v,&test_my_data);
42
1
    EXPECT_STREQ(ret.c_str(),"ok - confirmation msg server response: END \n");
43
1
}
44
45
TEST_F(command_help_Class_fixture, nonExistingCommand)
46
1
{
47
1
    std::unique_ptr<commandHandlerRoot> chr = std::make_unique<commandHandlerRoot>(&test_my_data);
48
1
    test_v.push_back("help");
49
1
    test_v.push_back("okdoki");
50
1
    auto ret = test_command_help->execute(test_v,&test_my_data);
51
    EXPECT_STREQ(ret.c_str(),"unknown command: okdoki help note not found");
52
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_idom_BT.cpp
Line
Count
Source
1
#include <gtest/gtest.h>
2
3
#include "../command_idom.h"
4
#include "../../../functions/functions.h"
5
#include "../../../RADIO_433_eq/radio_433_eq.h"
6
#include "../../../433MHz/RFLink/rflinkhandler.h"
7
#include "../../../iDomTools/test/iDomTools_fixture.h"
8
#include "../../../thread_functions/iDom_thread.h"
9
10
class commandiDom_Class_fixture : public iDomTOOLS_ClassTest
11
{
12
public:
13
    commandiDom_Class_fixture()
14
20
    {
15
20
        this->test_command_iDom = std::nullptr_t();
16
20
        this->test_RFLink = std::nullptr_t();
17
20
    }
18
19
protected:
20
    std::vector<std::string> test_v= {"iDom"};
21
    RFLinkHandler* test_RFLink;
22
    blockQueue test_q;
23
    command_iDom* test_command_iDom;
24
25
    void SetUp() final
26
20
    {
27
20
        iDomTOOLS_ClassTest::SetUp();
28
20
29
20
        test_q._clearAll();
30
20
31
20
        test_RFLink = new RFLinkHandler(&test_my_data);
32
20
        test_command_iDom = new command_iDom("iDom");
33
20
        test_my_data.main_RFLink = test_RFLink;
34
20
        std::cout << "commandiDom_Class_fixture SetUp" << std::endl;
35
20
    }
36
37
    void TearDown() final
38
20
    {
39
20
        iDomTOOLS_ClassTest::TearDown();
40
20
        delete test_RFLink;
41
20
        delete test_command_iDom;
42
20
        std::cout << "commandiDom_Class_fixture TearDown" << std::endl;
43
20
    }
44
};
45
46
TEST_F(commandiDom_Class_fixture, getName)
47
1
{
48
1
    EXPECT_THAT(test_command_iDom->getCommandName(),testing::HasSubstr("iDom"));
49
1
}
50
51
TEST_F(commandiDom_Class_fixture, help)
52
1
{
53
1
    std::string helpStr = test_command_iDom->help();
54
1
    EXPECT_THAT(helpStr,testing::HasSubstr("iDom"));
55
1
    std::cout << "test " << helpStr.size() << std::endl;
56
1
    EXPECT_EQ(helpStr.size(),1189);
57
1
}
58
59
TEST_F(commandiDom_Class_fixture, less_param)
60
1
{
61
1
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
62
1
    EXPECT_THAT(retStr,testing::HasSubstr("need parameter!"));
63
1
}
64
TEST_F(commandiDom_Class_fixture, unknonw_para)
65
1
{
66
1
    test_v.push_back("fake");
67
1
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
68
1
    EXPECT_THAT(retStr,testing::HasSubstr("iDom - unknown parameter:"));
69
1
}
70
71
TEST_F(commandiDom_Class_fixture, speakers)
72
1
{
73
1
    test_my_data.main_iDomTools->unlockHome();
74
1
    //////////////// fake command
75
1
    test_v.push_back("speakers");
76
1
    test_v.push_back("fake");
77
1
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
78
1
    EXPECT_THAT(retStr,testing::HasSubstr("unknow speakers action: fake"));
79
1
    ///////////////// ON
80
1
    test_my_data.main_iDomStatus->setObjectState("speakers",STATE::UNDEFINE);
81
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("speakers"), STATE::UNDEFINE);
82
1
    test_v.clear();
83
1
    test_v.push_back("iDom");
84
1
    test_v.push_back("speakers");
85
1
    test_v.push_back("ON");
86
1
    retStr = test_command_iDom->execute(test_v, &test_my_data);
87
1
    EXPECT_THAT(retStr,testing::HasSubstr("speakers ON"));
88
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("speakers"), STATE::ON);
89
1
    ///////////////// OFF
90
1
    test_v.clear();
91
1
    test_v.push_back("iDom");
92
1
    test_v.push_back("speakers");
93
1
    test_v.push_back("OFF");
94
1
    retStr = test_command_iDom->execute(test_v, &test_my_data);
95
1
    EXPECT_THAT(retStr,testing::HasSubstr("speakers OFF"));
96
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("speakers"), STATE::OFF);
97
1
}
98
99
TEST_F(commandiDom_Class_fixture, sunset_sunrise)
100
1
{
101
1
    test_v.clear();
102
1
    test_v.push_back("iDom");
103
1
    test_v.push_back("sunset");
104
1
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
105
1
    std::cout << "retString: " << retStr << std::endl;
106
1
    EXPECT_THAT(retStr,testing::HasSubstr("Sunset time:"));
107
1
108
1
    test_v.clear();
109
1
    test_v.push_back("iDom");
110
1
    test_v.push_back("sunrise");
111
1
    retStr = test_command_iDom->execute(test_v, &test_my_data);
112
1
    std::cout << "retString: " << retStr << std::endl;
113
1
    EXPECT_THAT(retStr,testing::HasSubstr("Sunrise time:"));
114
1
}
115
116
TEST_F(commandiDom_Class_fixture, day_lenght)
117
1
{
118
1
    test_v.clear();
119
1
    test_v.push_back("iDom");
120
1
    test_v.push_back("day");
121
1
    test_v.push_back("lenght");
122
1
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
123
1
    std::cout << "retString: " << retStr << std::endl;
124
1
    EXPECT_THAT(retStr,testing::HasSubstr("Day Lenght :"));
125
1
}
126
127
TEST_F(commandiDom_Class_fixture, sun)
128
1
{
129
1
    test_v.clear();
130
1
    test_v.push_back("iDom");
131
1
    test_v.push_back("sun");
132
1
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
133
1
    std::cout << "retString: " << retStr << std::endl;
134
1
    EXPECT_THAT(retStr,testing::HasSubstr("Day Lenght :"));
135
1
}
136
137
TEST_F(commandiDom_Class_fixture, sysinfo)
138
1
{
139
1
    test_v.clear();
140
1
    test_v.push_back("iDom");
141
1
    test_v.push_back("sysinfo");
142
1
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
143
1
    std::cout << "retString: " << retStr << std::endl;
144
1
    EXPECT_THAT(retStr,testing::HasSubstr("free RAM"));
145
1
}
146
147
TEST_F(commandiDom_Class_fixture, temperature)
148
1
{
149
1
    TEST_DATA::return_send_to_arduino = "-12:22";
150
1
    test_v.clear();
151
1
    test_v.push_back("iDom");
152
1
    test_v.push_back("temperature");
153
1
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
154
1
    std::cout << "retString: " << retStr << std::endl;
155
1
    EXPECT_THAT(retStr,testing::HasSubstr("-12:22"));
156
1
157
1
    test_v.clear();
158
1
    test_v.push_back("iDom");
159
1
    test_v.push_back("temperature");
160
1
    test_v.push_back("stats");
161
1
    test_v.push_back("insideee");
162
1
    retStr = test_command_iDom->execute(test_v, &test_my_data);
163
1
    std::cout << "retString: " << retStr << std::endl;
164
1
    EXPECT_THAT(retStr,testing::HasSubstr("not found!"));
165
1
}
166
167
TEST_F(commandiDom_Class_fixture, text)
168
1
{
169
1
    TEST_DATA::return_send_to_arduino = "-12:22";
170
1
    test_v.clear();
171
1
    test_v.push_back("iDom");
172
1
    test_v.push_back("text");
173
1
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
174
1
    std::cout << "retString: " << retStr << std::endl;
175
1
    EXPECT_THAT(retStr,testing::HasSubstr("Godzina"));
176
1
}
177
178
TEST_F(commandiDom_Class_fixture, lock_unlock)
179
1
{
180
1
    test_v.clear();
181
1
    test_v.push_back("iDom");
182
1
    test_v.push_back("lock");
183
1
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
184
1
    std::cout << "retString: " << retStr << std::endl;
185
1
    EXPECT_EQ(test_my_data.idom_all_state.houseState, STATE::LOCK);
186
1
187
1
    test_v.clear();
188
1
    test_v.push_back("iDom");
189
1
    test_v.push_back("unlock");
190
1
    retStr = test_command_iDom->execute(test_v, &test_my_data);
191
1
    std::cout << "retString: " << retStr << std::endl;
192
1
    EXPECT_EQ(test_my_data.idom_all_state.houseState, STATE::UNLOCK);
193
1
}
194
195
TEST_F(commandiDom_Class_fixture, t_230V)
196
1
{
197
1
    test_my_data.main_iDomTools->unlockHome();
198
1
    //////////////// fake command
199
1
    test_v.push_back("230V");
200
1
    test_v.push_back("fake");
201
1
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
202
1
    EXPECT_THAT(retStr,testing::HasSubstr("wrong paramiter"));
203
1
    ///////////////// ON
204
1
    test_my_data.main_iDomStatus->setObjectState("printer",STATE::UNDEFINE);
205
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("printer"), STATE::UNDEFINE);
206
1
    test_v.clear();
207
1
    test_v.push_back("iDom");
208
1
    test_v.push_back("230V");
209
1
    test_v.push_back("ON");
210
1
    retStr = test_command_iDom->execute(test_v, &test_my_data);
211
1
    std::cout << "retString: " << retStr << std::endl;
212
1
    EXPECT_THAT(retStr,testing::HasSubstr("230V ON"));
213
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("printer"), STATE::ON);
214
1
    ///////////////// OFF
215
1
    test_v.clear();
216
1
    test_v.push_back("iDom");
217
1
    test_v.push_back("230V");
218
1
    test_v.push_back("OFF");
219
1
    retStr = test_command_iDom->execute(test_v, &test_my_data);
220
1
    std::cout << "retString: " << retStr << std::endl;
221
1
    EXPECT_THAT(retStr,testing::HasSubstr("230V OFF"));
222
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("printer"), STATE::OFF);
223
1
}
224
225
TEST_F(commandiDom_Class_fixture, smog)
226
1
{
227
1
    test_v.clear();
228
1
    test_v.push_back("iDom");
229
1
    test_v.push_back("smog");
230
1
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
231
1
    std::cout << "retString: " << retStr << std::endl;
232
1
    EXPECT_THAT(retStr,testing::HasSubstr(" mg/m^3"));
233
1
}
234
235
TEST_F(commandiDom_Class_fixture, say)
236
1
{
237
1
    Clock::setTime_forBT_usage(23,23);
238
1
    TEST_DATA::return_send_to_arduino = "-3:6";
239
1
    test_v.clear();
240
1
    test_v.push_back("iDom");
241
1
    test_v.push_back("say");
242
1
    test_v.push_back("dummy");
243
1
    test_v.push_back("dummy");
244
1
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
245
1
    std::cout << "retString: " << retStr << std::endl;
246
1
    //EXPECT_THAT(retStr,testing::HasSubstr("sad"));
247
1
}
248
TEST_F(commandiDom_Class_fixture, wifi)
249
1
{
250
1
    TEST_DATA::return_httpPost = "ok";
251
1
    test_v.clear();
252
1
    test_v.push_back("iDom");
253
1
    test_v.push_back("wifi");
254
1
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
255
1
    std::cout << "retString: " << retStr << std::endl;
256
1
    EXPECT_THAT(retStr,testing::HasSubstr("ok"));
257
1
}
258
259
TEST_F(commandiDom_Class_fixture, lightning)
260
1
{
261
1
    test_v.clear();
262
1
    test_v.push_back("iDom");
263
1
    test_v.push_back("lightning");
264
1
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
265
1
    std::cout << "retString: " << retStr << std::endl;
266
1
    EXPECT_THAT(retStr,testing::HasSubstr("bool: "));
267
1
}
268
269
TEST_F(commandiDom_Class_fixture, camera)
270
1
{
271
1
    test_my_data.server_settings->cameraLedOFF = "cameraOFF";
272
1
    test_my_data.server_settings->cameraLedON = "cameraON";
273
1
274
1
    Clock::setTime_forBT_usage(23,23);
275
1
    test_v.clear();
276
1
    test_v.push_back("iDom");
277
1
    test_v.push_back("camera");
278
1
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
279
1
    std::cout << "retString: " << retStr << std::endl;
280
1
    EXPECT_STREQ(retStr.c_str(),"not enough parameters");
281
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("cameraLED"),STATE::UNKNOWN);
282
1
    ////////////////////////////////////////// ON
283
1
    TEST_DATA::return_httpPost = "ok.\n";
284
1
    test_v.clear();
285
1
    test_v.push_back("iDom");
286
1
    test_v.push_back("camera");
287
1
    test_v.push_back("LED");
288
1
289
1
    test_v.push_back("ON");
290
1
    retStr = test_command_iDom->execute(test_v, &test_my_data);
291
1
    std::cout << "retString: " << retStr << std::endl;
292
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("cameraLED"),STATE::ON);
293
1
    EXPECT_STREQ(retStr.c_str(),"led DONE");
294
1
    ////////////////////////////////////////// OFF
295
1
    TEST_DATA::return_httpPost = "ok.\n";
296
1
    test_v.clear();
297
1
    test_v.push_back("iDom");
298
1
    test_v.push_back("camera");
299
1
    test_v.push_back("LED");
300
1
301
1
    test_v.push_back("OFF");
302
1
    retStr = test_command_iDom->execute(test_v, &test_my_data);
303
1
    std::cout << "retString: " << retStr << std::endl;
304
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("cameraLED"),STATE::OFF);
305
1
    EXPECT_STREQ(retStr.c_str(),"led DONE");
306
1
}
307
308
TEST_F(commandiDom_Class_fixture, LED)
309
1
{
310
1
    test_my_data.main_iDomTools->unlockHome();
311
1
312
1
    test_v.clear();
313
1
    test_v.push_back("iDom");
314
1
    test_v.push_back("LED");
315
1
    test_v.push_back("33");
316
1
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
317
1
    std::cout << "retString: " << retStr << std::endl;
318
1
    EXPECT_THAT(retStr,testing::HasSubstr("need more parameter from-to-R-G-B"));
319
1
320
1
    ///////////////////////////////////// OFF
321
1
    TEST_DATA::return_send_to_arduino = "led OFF";
322
1
323
1
    test_v.clear();
324
1
    test_v.push_back("iDom");
325
1
    test_v.push_back("LED");
326
1
    test_v.push_back("OFF");
327
1
    retStr = test_command_iDom->execute(test_v, &test_my_data);
328
1
    std::cout << "retString: " << retStr << std::endl;
329
1
    EXPECT_THAT(retStr,testing::HasSubstr("led OFF"));
330
1
}
331
TEST_F(commandiDom_Class_fixture, kodi)
332
1
{
333
1
    test_my_data.main_iDomStatus->setObjectState("KODI",STATE::ACTIVE);
334
1
    test_v.clear();
335
1
    test_v.push_back("iDom");
336
1
    test_v.push_back("KODI");
337
1
    std::string retStr = test_command_iDom->execute(test_v, &test_my_data);
338
1
339
1
    std::cout << "retString: " << retStr << std::endl;
340
1
    EXPECT_STREQ(retStr.c_str(),"kodi already run");
341
1
342
1
    test_my_data.main_iDomStatus->setObjectState("KODI",STATE::DEACTIVE);
343
1
    test_my_data.main_iDomStatus->setObjectState("music",STATE::PLAY);
344
1
    test_my_data.main_iDomStatus->setObjectState("speakers",STATE::ON);
345
1
346
1
    std::array<Thread_array_struc,iDomConst::MAX_CONNECTION> test_ThreadArrayStruc;
347
1
348
11
    for (int i = 0 ; i < iDomConst::MAX_CONNECTION; i++)
349
10
        test_ThreadArrayStruc.at(i).thread_socket = i+1;
350
1
    test_ThreadArrayStruc.at(3).thread_socket = 0;
351
1
    test_my_data.main_THREAD_arr = &test_ThreadArrayStruc;
352
1
353
1
    test_v.clear();
354
1
    test_v.push_back("iDom");
355
1
    test_v.push_back("KODI");
356
1
    retStr = test_command_iDom->execute(test_v, &test_my_data);
357
1
358
1
    sleep(1);
359
1
    std::cout << "retString: " << retStr << std::endl;
360
1
    EXPECT_THAT(retStr,testing::HasSubstr("STARTED"));
361
1
362
11
    for (int i = 0 ; i < iDomConst::MAX_CONNECTION; i++)
363
10
        test_ThreadArrayStruc[i].thread_socket = -1;
364
1
    test_v.clear();
365
1
    test_v.push_back("iDom");
366
1
    test_v.push_back("KODI");
367
1
    retStr = test_command_iDom->execute(test_v, &test_my_data);
368
1
369
1
    std::cout << "retString: " << retStr << std::endl;
370
    EXPECT_STREQ(retStr.c_str(),"not free space to new thread");
371
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_ip_BT.cpp
Line
Count
Source
1
#include "../command_ip.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_ip_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_ip_Class_fixture()
8
1
    {
9
1
10
1
    }
11
12
protected:
13
    std::unique_ptr<command_ip> test_command_ip;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
17
1
    {
18
1
        iDomTOOLS_ClassTest::SetUp();
19
1
        test_command_ip =  std::make_unique <command_ip> ("ip");
20
1
    }
21
22
    void TearDown() final
23
1
    {
24
1
        iDomTOOLS_ClassTest::TearDown();
25
1
    }
26
};
27
28
TEST_F(command_ip_Class_fixture, main)
29
1
{
30
1
    test_my_data.server_settings->SERVER_IP = "100.001.1.0";
31
1
    test_v.push_back("ip");
32
1
    auto ret = test_command_ip->execute(test_v,&test_my_data);
33
    EXPECT_STREQ(ret.c_str(),"iDom server IP: 100.001.1.0");
34
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_log_BT.cpp
Line
Count
Source
1
#include "../command_log.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_log_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_log_Class_fixture()
8
1
    {
9
1
10
1
    }
11
12
protected:
13
    std::unique_ptr<command_log> test_command_log;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
17
1
    {
18
1
        iDomTOOLS_ClassTest::SetUp();
19
1
        test_command_log = std::make_unique <command_log> ("log");
20
1
    }
21
22
    void TearDown() final
23
1
    {
24
1
        iDomTOOLS_ClassTest::TearDown();
25
1
    }
26
};
27
28
TEST_F(command_log_Class_fixture, main)
29
1
{
30
1
    test_v.clear();
31
1
    test_v.push_back("log");
32
1
    test_v.push_back("INFOoo");
33
1
    test_v.push_back("test");
34
1
    auto ret = test_command_log->execute(test_v,&test_my_data);
35
1
    EXPECT_THAT(ret, ::testing::HasSubstr("DONE!"));
36
1
37
1
    test_v.clear();
38
1
    test_v.push_back("log");
39
1
    test_v.push_back("INFO");
40
1
    test_v.push_back("test");
41
1
    ret = test_command_log->execute(test_v,&test_my_data);
42
1
    EXPECT_THAT(ret, ::testing::HasSubstr("DONE!"));
43
1
44
1
    test_v.clear();
45
1
    test_v.push_back("log");
46
1
    test_v.push_back("DEBUG");
47
1
    test_v.push_back("test");
48
1
    ret = test_command_log->execute(test_v,&test_my_data);
49
1
    EXPECT_THAT(ret, ::testing::HasSubstr("DONE!"));
50
1
51
1
    test_v.clear();
52
1
    test_v.push_back("log");
53
1
    test_v.push_back("WARNING");
54
1
    test_v.push_back("test");
55
1
    ret = test_command_log->execute(test_v,&test_my_data);
56
1
    EXPECT_THAT(ret, ::testing::HasSubstr("DONE!"));
57
1
    test_v.clear();
58
1
    test_v.push_back("log");
59
1
    test_v.push_back("ERROR");
60
1
    test_v.push_back("test");
61
1
    ret = test_command_log->execute(test_v,&test_my_data);
62
1
    EXPECT_THAT(ret, ::testing::HasSubstr("DONE!"));
63
1
    test_v.clear();
64
1
    test_v.push_back("log");
65
1
    test_v.push_back("FATAL");
66
1
    test_v.push_back("test");
67
1
    ret = test_command_log->execute(test_v,&test_my_data);
68
1
    EXPECT_THAT(ret, ::testing::HasSubstr("DONE!"));
69
1
    test_v.clear();
70
1
    test_v.push_back("log");
71
1
    test_v.push_back("CRITICAL");
72
1
    test_v.push_back("test");
73
1
    ret = test_command_log->execute(test_v,&test_my_data);
74
1
    EXPECT_THAT(ret, ::testing::HasSubstr("DONE!"));
75
1
    test_v.clear();
76
1
    test_v.push_back("log");
77
1
    test_v.push_back("VERBOSE");
78
1
    test_v.push_back("test");
79
1
    ret = test_command_log->execute(test_v,&test_my_data);
80
    EXPECT_THAT(ret, ::testing::HasSubstr("DONE!"));
81
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_mpd_BT.cpp
Line
Count
Source
1
#include "../command_mpd.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_mpd_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_mpd_Class_fixture()
8
9
    {
9
9
10
9
    }
11
12
protected:
13
    std::unique_ptr<command_mpd> test_command_mpd;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
17
9
    {
18
9
        iDomTOOLS_ClassTest::SetUp();
19
9
        test_command_mpd = std::make_unique <command_mpd> ("mpd");
20
9
    }
21
22
    void TearDown() final
23
9
    {
24
9
        iDomTOOLS_ClassTest::TearDown();
25
9
    }
26
};
27
28
TEST_F(command_mpd_Class_fixture, unknownParameter)
29
1
{
30
1
    test_v.clear();
31
1
    test_v.push_back("mpd");
32
1
    test_v.push_back("test");
33
1
    auto ret = test_command_mpd->execute(test_v,&test_my_data);
34
1
    EXPECT_STREQ(ret.c_str(), "unknown parameter test");
35
1
36
1
 }
37
38
TEST_F(command_mpd_Class_fixture, list)
39
1
{
40
1
    test_my_data.ptr_MPD_info->songList = {"song 1","song 2","song 3"};
41
1
    test_v.clear();
42
1
    test_v.push_back("mpd");
43
1
    test_v.push_back("list");
44
1
    auto ret = test_command_mpd->execute(test_v,&test_my_data);
45
1
    EXPECT_STREQ(ret.c_str(), "song 1\nsong 2\nsong 3\n");
46
1
 }
47
48
TEST_F(command_mpd_Class_fixture, get)
49
1
{
50
1
    test_my_data.ptr_MPD_info->volume = 33;
51
1
    test_my_data.ptr_MPD_info->radio = "radio test";
52
1
    test_my_data.ptr_MPD_info->title = "title test";
53
1
54
1
    test_v.clear();
55
1
    test_v.push_back("mpd");
56
1
    test_v.push_back("get");
57
1
    test_v.push_back("volume");
58
1
59
1
    auto ret = test_command_mpd->execute(test_v,&test_my_data);
60
1
    EXPECT_STREQ(ret.c_str(), "33");
61
1
62
1
    test_v.clear();
63
1
    test_v.push_back("mpd");
64
1
    test_v.push_back("get");
65
1
    test_v.push_back("info");
66
1
67
1
    ret = test_command_mpd->execute(test_v,&test_my_data);
68
1
    EXPECT_STREQ(ret.c_str(), "radio test : title test");
69
1
 }
70
TEST_F(command_mpd_Class_fixture, volume)
71
1
{
72
1
    test_my_data.ptr_MPD_info->volume = 33;
73
1
74
1
    test_v.clear();
75
1
    test_v.push_back("mpd");
76
1
    test_v.push_back("volume");
77
1
    test_v.push_back("up");
78
1
79
1
    blockQueue test_q;
80
1
    test_q._clearAll();
81
1
82
1
    test_command_mpd->execute(test_v,&test_my_data);
83
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::VOLUP);
84
1
85
1
    test_v.clear();
86
1
    test_v.push_back("mpd");
87
1
    test_v.push_back("volume");
88
1
    test_v.push_back("down");
89
1
90
1
    test_command_mpd->execute(test_v,&test_my_data);
91
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::VOLDOWN);
92
1
93
1
    test_v.clear();
94
1
    test_v.push_back("mpd");
95
1
    test_v.push_back("volume");
96
1
    test_v.push_back("55");
97
1
98
1
    test_command_mpd->execute(test_v,&test_my_data);
99
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::VOLSET);
100
1
    EXPECT_EQ(test_my_data.ptr_MPD_info->volume, 55);
101
1
    /////// voule -gt 100%
102
1
    test_v.clear();
103
1
    test_v.push_back("mpd");
104
1
    test_v.push_back("volume");
105
1
    test_v.push_back("155");
106
1
107
1
    test_command_mpd->execute(test_v,&test_my_data);
108
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::NULL_);
109
1
    EXPECT_EQ(test_my_data.ptr_MPD_info->volume, 55);
110
1
 }
111
112
TEST_F(command_mpd_Class_fixture, pause)
113
1
{
114
1
    test_v.clear();
115
1
    test_v.push_back("mpd");
116
1
    test_v.push_back("pause");
117
1
118
1
    blockQueue test_q;
119
1
    test_q._clearAll();
120
1
121
1
    auto ret = test_command_mpd->execute(test_v,&test_my_data);
122
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::PAUSE);
123
1
    EXPECT_STREQ(ret.c_str(), "paused!");
124
1
}
125
126
TEST_F(command_mpd_Class_fixture, next)
127
1
{
128
1
    test_v.clear();
129
1
    test_v.push_back("mpd");
130
1
    test_v.push_back("next");
131
1
132
1
    blockQueue test_q;
133
1
    test_q._clearAll();
134
1
135
1
    test_command_mpd->execute(test_v,&test_my_data);
136
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::NEXT);
137
1
}
138
139
TEST_F(command_mpd_Class_fixture, prev)
140
1
{
141
1
    test_v.clear();
142
1
    test_v.push_back("mpd");
143
1
    test_v.push_back("prev");
144
1
145
1
    blockQueue test_q;
146
1
    test_q._clearAll();
147
1
148
1
    test_command_mpd->execute(test_v,&test_my_data);
149
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::PREV);
150
1
}
151
152
TEST_F(command_mpd_Class_fixture, stop)
153
1
{
154
1
    test_v.clear();
155
1
    test_v.push_back("mpd");
156
1
    test_v.push_back("stop");
157
1
158
1
    blockQueue test_q;
159
1
    test_q._clearAll();
160
1
161
1
    auto ret = test_command_mpd->execute(test_v,&test_my_data);
162
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::STOP);
163
1
    EXPECT_STREQ(ret.c_str(), "stoped!");
164
1
}
165
166
TEST_F(command_mpd_Class_fixture, play_playID)
167
1
{
168
1
    test_my_data.idom_all_state.houseState = STATE::UNLOCK;
169
1
    test_my_data.ptr_MPD_info->currentSongID = 2;
170
1
    test_my_data.ptr_MPD_info->songList = {"song 1","song 2","song 3"};
171
1
172
1
    test_v.clear();
173
1
    test_v.push_back("mpd");
174
1
    test_v.push_back("start");
175
1
176
1
    blockQueue test_q;
177
1
    test_q._clearAll();
178
1
179
1
    test_command_mpd->execute(test_v,&test_my_data);
180
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::PLAY);
181
1
182
1
    test_v.clear();
183
1
    test_v.push_back("mpd");
184
1
    test_v.push_back("start");
185
1
    test_v.push_back("3");
186
1
187
1
    test_q._clearAll();
188
1
189
1
    test_command_mpd->execute(test_v,&test_my_data);
190
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::PLAY_ID);
191
    EXPECT_EQ(test_my_data.ptr_MPD_info->currentSongID, 3);
192
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_ok_BT.cpp
Line
Count
Source
1
#include "../command_ok.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_ok_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_ok_Class_fixture()
8
1
    {
9
1
10
1
    }
11
12
protected:
13
    std::unique_ptr<command_ok> test_command_ok;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
17
1
    {
18
1
        iDomTOOLS_ClassTest::SetUp();
19
1
        test_command_ok =  std::make_unique <command_ok> ("ok");
20
1
    }
21
22
    void TearDown() final
23
1
    {
24
1
        iDomTOOLS_ClassTest::TearDown();
25
1
    }
26
};
27
28
TEST_F(command_ok_Class_fixture, main)
29
1
{
30
1
    test_v.push_back("ok");
31
1
    auto ret = test_command_ok->execute(test_v,&test_my_data);
32
    EXPECT_STREQ(ret.c_str(),"\nEND\n");
33
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_program_BT.cpp
Line
Count
Source
1
#include "../command_program.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_program_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_program_Class_fixture()
8
9
    {
9
9
10
9
    }
11
12
protected:
13
    std::unique_ptr<command_program> test_command_program;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
17
9
    {
18
9
        iDomTOOLS_ClassTest::SetUp();
19
9
        test_command_program = std::make_unique <command_program> ("program");
20
9
    }
21
22
    void TearDown() final
23
9
    {
24
9
        iDomTOOLS_ClassTest::TearDown();
25
9
    }
26
};
27
28
TEST_F(command_program_Class_fixture, unknownParameter)
29
1
{
30
1
    test_v.clear();
31
1
    test_v.push_back("program");
32
1
    test_v.push_back("test");
33
1
    auto ret = test_command_program->execute(test_v,&test_my_data);
34
1
    EXPECT_STREQ(ret.c_str(), "add more paramiters");
35
1
36
1
}
37
38
TEST_F(command_program_Class_fixture, missingParameter)
39
1
{
40
1
    test_v.clear();
41
1
    test_v.push_back("program");
42
1
    auto ret = test_command_program->execute(test_v,&test_my_data);
43
1
    EXPECT_THAT(ret, ::testing::HasSubstr("what?"));
44
1
}
45
46
TEST_F(command_program_Class_fixture, fakeParameter)
47
1
{
48
1
    test_v.clear();
49
1
    test_v.push_back("program");
50
1
    test_v.push_back("fake");
51
1
    test_v.push_back("fake2");
52
1
    auto ret = test_command_program->execute(test_v,&test_my_data);
53
1
    EXPECT_THAT(ret, ::testing::HasSubstr("what? - fake"));
54
1
}
55
56
TEST_F(command_program_Class_fixture, stopProgram)
57
1
{
58
1
    test_v.clear();
59
1
    test_v.push_back("program");
60
1
    test_v.push_back("stop");
61
1
    EXPECT_THROW(test_command_program->execute(test_v,&test_my_data), std::string);
62
1
}
63
64
TEST_F(command_program_Class_fixture, programReloadSoft)
65
1
{
66
1
    test_v.clear();
67
1
    test_v.push_back("program");
68
1
    test_v.push_back("reload");
69
1
    test_v.push_back("soft");
70
1
    EXPECT_THROW(test_command_program->execute(test_v,&test_my_data), std::string);
71
1
    EXPECT_EQ(test_my_data.iDomProgramState, iDomStateEnum::RELOAD);
72
1
}
73
74
TEST_F(command_program_Class_fixture, programReloadHard)
75
1
{
76
1
    test_v.clear();
77
1
    test_v.push_back("program");
78
1
    test_v.push_back("reload");
79
1
    test_v.push_back("hard");
80
1
    EXPECT_THROW(test_command_program->execute(test_v,&test_my_data), std::string);
81
1
    EXPECT_EQ(test_my_data.iDomProgramState, iDomStateEnum::HARD_RELOAD);
82
1
}
83
84
TEST_F(command_program_Class_fixture, clearRamProgram)
85
1
{
86
1
    test_v.clear();
87
1
    test_v.push_back("program");
88
1
    test_v.push_back("clear");
89
1
    test_v.push_back("ram");
90
1
    auto ret = test_command_program->execute(test_v,&test_my_data);
91
1
    EXPECT_STREQ(ret.c_str(),"ram has beed freed");
92
1
}
93
94
TEST_F(command_program_Class_fixture, raspberryProgram)
95
1
{
96
1
    test_v.clear();
97
1
    test_v.push_back("program");
98
1
    test_v.push_back("raspberry");
99
1
    test_v.push_back("command");
100
1
    auto ret = test_command_program->execute(test_v,&test_my_data);
101
1
    EXPECT_STREQ(ret.c_str(),"command done with exitcode: 0");
102
1
}
103
104
TEST_F(command_program_Class_fixture, debugeVariableProgram)
105
1
{
106
1
    RFLinkHandler test_RFLinkkHandler(&test_my_data);
107
1
108
1
    test_my_data.main_RFLink = &test_RFLinkkHandler;
109
1
    test_my_data.main_RFLink->okTime = 777;
110
1
    test_my_data.main_RFLink->pingTime = 888;
111
1
    test_my_data.server_settings->PORT = 88;
112
1
    test_my_data.server_settings->v_delay = 1;
113
1
    test_my_data.sleeper = 1;
114
1
    test_my_data.now_time = 123;
115
1
    test_my_data.start = 12;
116
1
    int32_t buf = 1;
117
1
    unsigned int who = 0;
118
1
    test_my_data.pointer.ptr_buf = &buf;
119
1
    test_my_data.pointer.ptr_who = &who;
120
1
121
1
    test_v.clear();
122
1
    test_v.push_back("program");
123
1
    test_v.push_back("debuge");
124
1
    test_v.push_back("variable");
125
1
    auto ret = test_command_program->execute(test_v,&test_my_data);
126
1
    std::cout << ret << std::endl;
127
    EXPECT_THAT(ret,testing::HasSubstr("END"));
128
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_put_BT.cpp
Line
Count
Source
1
#include "../command_put.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_put_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_put_Class_fixture()
8
1
    {
9
1
10
1
    }
11
12
protected:
13
    std::unique_ptr<command_put> test_command_put;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
17
1
    {
18
1
        iDomTOOLS_ClassTest::SetUp();
19
1
        test_command_put = std::make_unique <command_put> ("put");
20
1
    }
21
22
    void TearDown() final
23
1
    {
24
1
        iDomTOOLS_ClassTest::TearDown();
25
1
    }
26
};
27
28
TEST_F(command_put_Class_fixture, main)
29
1
{
30
1
    TEST_DATA::return_send_to_arduino = "-2:3";
31
1
32
1
    test_v.push_back("put");
33
1
    test_v.push_back("temperature");
34
1
    auto ret = test_command_put->execute(test_v,&test_my_data);
35
    EXPECT_STREQ(ret.c_str(), "DONE");
36
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_rs232_BT.cpp
Line
Count
Source
1
#include "../commandrs232.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_RS232_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_RS232_Class_fixture()
8
8
    {
9
8
10
8
    }
11
12
protected:
13
    std::unique_ptr<commandRS232> test_command_put;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
17
8
    {
18
8
        iDomTOOLS_ClassTest::SetUp();
19
8
        test_command_put = std::make_unique <commandRS232> ("RS232");
20
8
    }
21
22
    void TearDown() final
23
8
    {
24
8
        iDomTOOLS_ClassTest::TearDown();
25
8
    }
26
};
27
28
TEST_F(command_RS232_Class_fixture, wrongParameter)
29
1
{
30
1
    test_v.push_back("RS232");
31
1
    test_v.push_back("test_par");
32
1
    auto ret = test_command_put->execute(test_v,&test_my_data);
33
1
    EXPECT_STREQ(ret.c_str(), "wrong parameter: test_par");
34
1
}
35
36
TEST_F(command_RS232_Class_fixture, getWrongParameter)
37
1
{
38
1
    test_v.push_back("RS232");
39
1
    test_v.push_back("get");
40
1
    test_v.push_back("fake");
41
1
    auto ret = test_command_put->execute(test_v,&test_my_data);
42
1
    EXPECT_STREQ(ret.c_str(), "wrong parameter: fake");
43
1
}
44
45
TEST_F(command_RS232_Class_fixture, getTemperature)
46
1
{
47
1
    TEST_DATA::return_send_to_arduino = "-2:-21";
48
1
49
1
    test_v.push_back("RS232");
50
1
    test_v.push_back("get");
51
1
    test_v.push_back("temperature");
52
1
    auto ret = test_command_put->execute(test_v,&test_my_data);
53
1
    EXPECT_THAT(ret, ::testing::HasSubstr("-2:-21"));
54
1
}
55
56
TEST_F(command_RS232_Class_fixture, send)
57
1
{
58
1
    TEST_DATA::return_send_to_arduino = "done";
59
1
60
1
    test_v.push_back("RS232");
61
1
    test_v.push_back("send");
62
1
    test_v.push_back("test:33;");
63
1
    auto ret = test_command_put->execute(test_v,&test_my_data);
64
1
    EXPECT_STREQ(ret.c_str(), "done");
65
1
}
66
67
TEST_F(command_RS232_Class_fixture, errorMissingPara)
68
1
{
69
1
    TEST_DATA::return_send_to_arduino = "done";
70
1
71
1
    test_v.push_back("RS232");
72
1
    test_v.push_back("error");
73
1
    auto ret = test_command_put->execute(test_v,&test_my_data);
74
1
    EXPECT_STREQ(ret.c_str(), "add more parameter to error");
75
1
}
76
77
TEST_F(command_RS232_Class_fixture, errorTemperatureMissingPara)
78
1
{
79
1
    TEST_DATA::return_send_to_arduino = "done";
80
1
81
1
    test_v.push_back("RS232");
82
1
    test_v.push_back("error");
83
1
    test_v.push_back("Temperature");
84
1
    test_v.push_back("error");
85
1
    auto ret = test_command_put->execute(test_v,&test_my_data);
86
1
    EXPECT_STREQ(ret.c_str(), "default");
87
1
}
88
89
TEST_F(command_RS232_Class_fixture, msgTestMissing)
90
1
{
91
1
    TEST_DATA::return_send_to_arduino = "done";
92
1
93
1
    test_v.push_back("RS232");
94
1
    test_v.push_back("error");
95
1
    test_v.push_back("test");
96
1
    test_v.push_back("msg");
97
1
98
1
    test_v.push_back("fake msg");
99
1
100
1
    auto ret = test_command_put->execute(test_v,&test_my_data);
101
1
    EXPECT_STREQ(ret.c_str(), "DONE!");
102
1
}
103
104
TEST_F(command_RS232_Class_fixture, msgTestFake)
105
1
{
106
1
    TEST_DATA::return_send_to_arduino = "done";
107
1
108
1
    test_v.push_back("RS232");
109
1
    test_v.push_back("error");
110
1
    test_v.push_back("test");
111
1
    test_v.push_back("fake");;
112
1
113
1
    auto ret = test_command_put->execute(test_v,&test_my_data);
114
    EXPECT_STREQ(ret.c_str(), "default");
115
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_show_BT.cpp
Line
Count
Source
1
#include "../command_show.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_show_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_show_Class_fixture()
8
9
    {
9
9
10
9
    }
11
12
protected:
13
    std::unique_ptr<command_show> test_command_show;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
17
9
    {
18
9
        iDomTOOLS_ClassTest::SetUp();
19
9
        test_command_show = std::make_unique <command_show> ("show");
20
9
    }
21
22
    void TearDown() final
23
9
    {
24
9
        iDomTOOLS_ClassTest::TearDown();
25
9
    }
26
};
27
28
TEST_F(command_show_Class_fixture, wrongParameter)
29
1
{
30
1
    test_v.push_back("show");
31
1
    test_v.push_back("t");
32
1
    auto ret = test_command_show->execute(test_v,&test_my_data);
33
1
    EXPECT_STREQ(ret.c_str(), "wrong parameter: t");
34
1
}
35
36
TEST_F(command_show_Class_fixture, unknownParameter)
37
1
{
38
1
    test_v.push_back("show");
39
1
    auto ret = test_command_show->execute(test_v,&test_my_data);
40
1
    EXPECT_STREQ(ret.c_str(), "show what?");
41
1
}
42
43
TEST_F(command_show_Class_fixture, showThreadAll)
44
1
{
45
1
    std::array<Thread_array_struc, iDomConst::MAX_CONNECTION> threadArray;
46
1
47
1
    threadArray[1].thread_ID = std::this_thread::get_id();
48
1
    threadArray[1].thread_name = "thread1 test1";
49
1
    threadArray[1].thread_socket = 1;
50
1
    threadArray[2].thread_ID = std::this_thread::get_id();
51
1
    threadArray[2].thread_name = "thread1 test2";
52
1
    threadArray[2].thread_socket = 2;
53
1
54
1
    test_my_data.main_THREAD_arr = &threadArray;
55
1
56
1
    test_v.push_back("show");
57
1
    test_v.push_back("thread");
58
1
    test_v.push_back("all");
59
1
    auto ret = test_command_show->execute(test_v,&test_my_data);
60
1
    EXPECT_THAT(ret, testing::HasSubstr("socket: 2"));
61
1
}
62
63
TEST_F(command_show_Class_fixture, showThread)
64
1
{
65
1
    std::array<Thread_array_struc, iDomConst::MAX_CONNECTION> threadArray;
66
1
67
1
    threadArray[1].thread_ID = std::this_thread::get_id();
68
1
    threadArray[1].thread_name = "thread1 test1";
69
1
    threadArray[1].thread_socket = 1;
70
1
    threadArray[2].thread_ID = std::this_thread::get_id();
71
1
    threadArray[2].thread_name = "thread1 test2";
72
1
    threadArray[2].thread_socket = 2;
73
1
74
1
    test_my_data.main_THREAD_arr = &threadArray;
75
1
76
1
    test_v.push_back("show");
77
1
    test_v.push_back("thread");
78
1
    test_v.push_back("2");
79
1
    auto ret = test_command_show->execute(test_v,&test_my_data);
80
1
    EXPECT_THAT(ret, testing::HasSubstr("socket: 2"));
81
1
}
82
83
TEST_F(command_show_Class_fixture, showThreadNoId)
84
1
{
85
1
    test_v.push_back("show");
86
1
    test_v.push_back("thread");
87
1
    auto ret = test_command_show->execute(test_v,&test_my_data);
88
1
    EXPECT_STREQ(ret.c_str(), "No ID");
89
1
}
90
91
TEST_F(command_show_Class_fixture, showLog)
92
1
{
93
1
    test_v.push_back("show");
94
1
    test_v.push_back("log");
95
1
    auto ret = test_command_show->execute(test_v,&test_my_data);
96
1
    EXPECT_STREQ(ret.c_str(), "return test in l_send_file()");
97
1
}
98
99
TEST_F(command_show_Class_fixture, showLogNoInfo)
100
1
{
101
1
    test_v.push_back("show");
102
1
    test_v.push_back("log");
103
1
    test_v.push_back("no");
104
1
    test_v.push_back("INFO");
105
1
    auto ret = test_command_show->execute(test_v,&test_my_data);
106
1
    EXPECT_STREQ(ret.c_str(), "return test in l_send_file()");
107
1
}
108
109
TEST_F(command_show_Class_fixture, showLogInfo)
110
1
{
111
1
    test_v.push_back("show");
112
1
    test_v.push_back("log");
113
1
    test_v.push_back("INFO");
114
1
    auto ret = test_command_show->execute(test_v,&test_my_data);
115
1
    EXPECT_STREQ(ret.c_str(), "return test in l_send_file()");
116
1
}
117
118
TEST_F(command_show_Class_fixture, showLogFakeInfo)
119
1
{
120
1
    test_v.push_back("show");
121
1
    test_v.push_back("log");
122
1
    test_v.push_back("fake");
123
1
    test_v.push_back("INFO");
124
1
    auto ret = test_command_show->execute(test_v,&test_my_data);
125
    EXPECT_STREQ(ret.c_str(), "do you mean : show log no <string>?");
126
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_sleep_BT.cpp
Line
Count
Source
1
#include "../command_sleep.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_sleep_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_sleep_Class_fixture()
8
5
    {
9
5
10
5
    }
11
12
protected:
13
    std::unique_ptr<command_sleep> test_command_sleep;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
17
5
    {
18
5
        iDomTOOLS_ClassTest::SetUp();
19
5
        test_command_sleep = std::make_unique <command_sleep> ("sleep");
20
5
    }
21
22
    void TearDown() final
23
5
    {
24
5
        iDomTOOLS_ClassTest::TearDown();
25
5
    }
26
};
27
28
TEST_F(command_sleep_Class_fixture, sleep)
29
1
{
30
1
    test_my_data.sleeper = 88;
31
1
32
1
    test_v.push_back("sleep");
33
1
    auto ret = test_command_sleep->execute(test_v,&test_my_data);
34
1
    EXPECT_STREQ(ret.c_str(), "sleep set to: 88");
35
1
}
36
37
TEST_F(command_sleep_Class_fixture, sleepFakeParam)
38
1
{
39
1
    test_my_data.sleeper = 88;
40
1
41
1
    test_v.push_back("sleep");
42
1
    test_v.push_back("fake");
43
1
    auto ret = test_command_sleep->execute(test_v,&test_my_data);
44
1
    EXPECT_STREQ(ret.c_str(), "internal error");
45
1
}
46
47
TEST_F(command_sleep_Class_fixture, sleepFakeParam2)
48
1
{
49
1
    test_my_data.sleeper = 88;
50
1
51
1
    test_v.push_back("sleep");
52
1
    test_v.push_back("fake");
53
1
    test_v.push_back("fake2");
54
1
    auto ret = test_command_sleep->execute(test_v,&test_my_data);
55
1
    EXPECT_STREQ(ret.c_str(), "wrong parametr fake");
56
1
}
57
58
TEST_F(command_sleep_Class_fixture, sleepSetNoIntiger)
59
1
{
60
1
    test_my_data.sleeper = 88;
61
1
62
1
    test_v.push_back("sleep");
63
1
    test_v.push_back("set");
64
1
    test_v.push_back("fake2");
65
1
    auto ret = test_command_sleep->execute(test_v,&test_my_data);
66
1
    EXPECT_STREQ(ret.c_str(), "system need intiger > 0 not: fake2");
67
1
}
68
69
TEST_F(command_sleep_Class_fixture, sleepSet)
70
1
{
71
1
    std::array<Thread_array_struc, iDomConst::MAX_CONNECTION> threadArray;
72
1
73
1
    threadArray[1].thread_ID = std::this_thread::get_id();
74
1
    threadArray[1].thread_name = "thread1 test1";
75
1
    threadArray[1].thread_socket = 1;
76
1
    threadArray[2].thread_ID = std::this_thread::get_id();
77
1
    threadArray[2].thread_name = "thread1 test2";
78
1
    threadArray[2].thread_socket = 2;
79
1
80
1
    test_my_data.main_THREAD_arr = &threadArray;
81
1
82
1
    test_v.push_back("sleep");
83
1
    test_v.push_back("set");
84
1
    test_v.push_back("2");
85
1
    auto ret = test_command_sleep->execute(test_v,&test_my_data);
86
    EXPECT_STREQ(ret.c_str(), "DONE - Sleep MPD STARTED");
87
    sleep(1);
88
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_state_BT.cpp
Line
Count
Source
1
#include "../command_state.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_state_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_state_Class_fixture()
8
3
    {
9
3
10
3
    }
11
12
protected:
13
    std::unique_ptr<command_state> test_command_state;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
17
3
    {
18
3
        iDomTOOLS_ClassTest::SetUp();
19
3
        test_command_state = std::make_unique <command_state> ("state");
20
3
    }
21
22
    void TearDown() final
23
3
    {
24
3
        iDomTOOLS_ClassTest::TearDown();
25
3
    }
26
};
27
28
TEST_F(command_state_Class_fixture, stateAll)
29
1
{
30
1
    test_v.clear();
31
1
    test_v.push_back("state");
32
1
    test_v.push_back("all");
33
1
    auto ret = test_command_state->execute(test_v,&test_my_data);
34
1
    EXPECT_STREQ(ret.c_str(), "state: KODI=DEACTIVE alarm=DEACTIVE cameraLED=UNKNOWN house=UNDEFINE printer=OFF speakers=OFF ");
35
1
}
36
37
TEST_F(command_state_Class_fixture, stateGetOne)
38
1
{
39
1
    test_v.clear();
40
1
    test_v.push_back("state");
41
1
    test_v.push_back("KODI");
42
1
    auto ret = test_command_state->execute(test_v,&test_my_data);
43
1
    EXPECT_STREQ(ret.c_str(), "DEACTIVE");
44
1
}
45
46
TEST_F(command_state_Class_fixture, stateMissingParam)
47
1
{
48
1
    test_v.clear();
49
1
    test_v.push_back("state");
50
1
    auto ret = test_command_state->execute(test_v,&test_my_data);
51
    EXPECT_THAT(ret, testing::HasSubstr("need parameter!\n"));
52
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_test_BT.cpp
Line
Count
Source
1
#include "../commandtest.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_test_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_test_Class_fixture()
8
3
    {
9
3
10
3
    }
11
12
protected:
13
    std::unique_ptr<commandTEST> test_command_test;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
17
3
    {
18
3
        iDomTOOLS_ClassTest::SetUp();
19
3
        test_command_test = std::make_unique <commandTEST> ("test");
20
3
    }
21
22
    void TearDown() final
23
3
    {
24
3
        iDomTOOLS_ClassTest::TearDown();
25
3
    }
26
};
27
28
TEST_F(command_test_Class_fixture, test)
29
1
{
30
1
    test_v.push_back("test");
31
1
    test_v.push_back("test");
32
1
    auto ret = test_command_test->execute(test_v,&test_my_data);
33
1
    EXPECT_STREQ(ret.c_str(),"test - for test");
34
1
}
35
36
TEST_F(command_test_Class_fixture, throw)
37
1
{
38
1
    test_v.push_back("test");
39
1
    test_v.push_back("throw");
40
1
    EXPECT_THROW(test_command_test->execute(test_v,&test_my_data),std::string);
41
1
}
42
43
TEST_F(command_test_Class_fixture, unknownParam)
44
1
{
45
1
    test_v.push_back("test");
46
1
    test_v.push_back("fake");
47
1
    auto ret = test_command_test->execute(test_v,&test_my_data);
48
    EXPECT_EQ(ret.size(),49);
49
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_uptime_BT.cpp
Line
Count
Source
1
#include "../command_uptime.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_uptime_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_uptime_Class_fixture()
8
1
    {
9
1
10
1
    }
11
12
protected:
13
    std::unique_ptr<command_UPTIME> test_command_uptime;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
17
1
    {
18
1
        iDomTOOLS_ClassTest::SetUp();
19
1
        test_command_uptime = std::make_unique <command_UPTIME> ("uptime");
20
1
    }
21
22
    void TearDown() final
23
1
    {
24
1
        iDomTOOLS_ClassTest::TearDown();
25
1
    }
26
};
27
28
TEST_F(command_uptime_Class_fixture, main)
29
1
{
30
1
    time(&test_my_data.start);
31
1
    test_v.push_back("uptime");
32
1
    auto ret = test_command_uptime->execute(test_v,&test_my_data);
33
1
    std::cout << "DATA: " << ret << std::endl;
34
    EXPECT_STREQ(ret.c_str(),"uptime: \n0 day 0 hours 0 minutes 0 seconds");
35
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/command_433mhz.cpp
Line
Count
Source
1
#include "command_433mhz.h"
2
#include "../../RADIO_433_eq/radio_433_eq.h"
3
#include "../../433MHz/RFLink/rflinkhandler.h"
4
5
command_433MHz::command_433MHz(const std::string &name):command(name)
6
20
{
7
20
}
8
9
command_433MHz::~command_433MHz()
10
20
{
11
20
    // puts("command_433MHz::~command_433MHz()");
12
20
}
13
14
std::string command_433MHz::execute(std::vector<std::string> &v, thread_data *my_data)
15
40
{
16
40
    std::string str_buf = "wrong paramiter\n" + help();
17
40
    if (v.size() > 2){
18
40
        //////////////////////////// switch
19
40
        if (v[1] == "show" && v[2] == "all"){
20
21
            str_buf = my_data->main_REC->listAllName();
21
21
        }
22
40
        else if (v[1] == "delete" && v.size() == 3)
23
19
        {
24
4
            if (my_data->main_REC->nameExist(v[2]) == false)
25
4
            {
26
1
                return "equipment "+ v[2]+" not exist ";
27
1
            }
28
4
            my_data->main_REC->deleteRadioEq(v[2]);
29
3
            str_buf = v[2] + " deleted";
30
3
        }
31
19
        else if (v[1] == "add" && v.size() > 3) //zmień tu
32
15
        {
33
7
            RADIO_EQ_CONFIG cfg;
34
7
           /* if(v[2] == "SWITCH" && v.size() == 12)
35
7
                cfg.set(v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11]); // zmień tu
36
7
            else*/ if(v[2] == "BUTTON" && v.size() >= 6)
37
7
                cfg.set(v[2],v[3],v[4],v[5],v[6]); // zmień tu
38
7
            else if(v[2] == "WEATHER" && v.size() >= 4)
39
6
                cfg.set(v[2],v[3],v[4]); // zmień tu
40
6
            else
41
6
            {
42
5
                if (v.size() != 12)
43
5
                    return "mising paramiter!";
44
5
                cfg.set(v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11]); // zmień tu
45
4
                //return v[2] + " " + v[3] + " " + v[4] + "add more paramiter or wrong type";
46
4
}
47
7
            /////////////////////////////////////////////////////////////
48
7
            if (my_data->main_REC->nameExist(v[3]) == true)
49
6
            {
50
1
                return "equipment "+ v[3]+" exist ";
51
1
            }
52
6
            try
53
5
            {
54
5
                my_data->main_REC->addRadioEq(cfg,v[2]);
55
5
            }
56
5
            catch(const WRONG_FORMAT& )
57
5
            {
58
1
                return "wrong type "+v[2];
59
1
            }
60
5
            catch(const std::invalid_argument& )
61
5
            {
62
1
                return "wrong ID "+v[4];
63
1
            }
64
5
65
5
            str_buf = v[2] + " " + v[3] + " added";
66
3
            my_data->main_REC->saveConfig(my_data->server_settings->radio433MHzConfigFile);
67
3
        }
68
15
        else if (v[1] == "show" && v[2] == "switch"){
69
1
            str_buf = "";
70
1
            for (auto m_switch : my_data->main_REC->getSwitchPointerVector())
71
5
            {
72
5
                str_buf.append(stateToString(m_switch->getState()) );
73
5
            }
74
1
        }
75
8
        else if (v[1] == "show" && v[2] == "aether"){
76
1
            str_buf.clear();
77
1
            for(auto itr = my_data->main_RFLink->rflinkMAP.begin();
78
3
                itr != my_data->main_RFLink->rflinkMAP.end();
79
2
                itr++)
80
2
            {
81
2
                str_buf += itr->second.read();
82
2
                str_buf += '\n';
83
2
            }
84
1
            str_buf += ".";
85
1
86
1
        }
87
7
        else if (v[1] == "send"){
88
1
            str_buf = "sended!;";
89
1
            my_data->main_RFLink->sendCommand(v[2]);
90
1
91
1
        }
92
6
        else if (v[1] == "switch"){
93
5
            try{
94
5
                RADIO_SWITCH *m_switch = dynamic_cast<RADIO_SWITCH*>(my_data->main_REC->getEqPointer(v[2]));
95
5
96
5
                if (v[3] == "ON") {
97
1
                    m_switch->on();
98
1
                    str_buf = " done ";
99
1
                }
100
5
                else if (v[3] == "OFF"){
101
1
                    m_switch->off();
102
1
                    str_buf = " done ";
103
1
                }
104
4
                else if (v[3] == "15s"){
105
1
                    m_switch->onFor15sec();
106
1
                    str_buf = " done ";
107
1
                }
108
3
                else{
109
2
                    str_buf = "unknown paramiter: ";
110
2
                    str_buf.append(v[3]);
111
2
                }
112
5
            }
113
5
            catch (std::string& error){
114
1
                str_buf = error;
115
1
            }
116
5
            my_data->main_iDomTools->saveState_iDom();
117
5
        }
118
40
        /////////////////////////////////////////////
119
40
    }
120
40
    return str_buf;
121
40
}
122
123
std::string command_433MHz::help()
124
41
{
125
41
    std::stringstream help;
126
41
    help << ("433MHz delete <name> - dalete radio equipment") <<std::endl;
127
41
    help << ("433MHz add <type> <name> <ID> <onCode> <offCode> <on15sec> <sunrise> <sunset> <lock> <unlock> - add radio equipment") <<std::endl;
128
41
    help << ("433MHz switch <name> ON/OFF/15s - change switch state") <<std::endl;
129
41
    help << ("433MHz show all - list all equipment by name") <<std::endl;
130
41
    help << ("433MHz show aether - show aether devices by ID") <<std::endl;
131
41
    help << ("433MHz send <msg> - send command") <<std::endl;
132
41
    return help.str();
133
41
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/command_ardu.cpp
Line
Count
Source
1
#include "command_ardu.h"
2
3
command_ardu::command_ardu(const std::string &name):command(name)
4
1
{
5
1
    this->m_mainRadioButton = std::nullptr_t();
6
1
}
7
8
command_ardu::command_ardu(const std::string& name, thread_data *my_data):command(name)
9
  ,m_button433MHzVector(my_data->main_REC->getButtonPointerVector())
10
18
{
11
18
    //m_button433MHzVector = my_data->main_REC->getButtonPointerVector();
12
18
    m_mainRadioButton = static_cast<RADIO_BUTTON*>(my_data->main_REC->getEqPointer("locker"));
13
18
14
18
    m_weatherStVe = my_data->main_REC->getWeather_StationPtrVector();
15
18
    m_mainWeatherStation = static_cast<RADIO_WEATHER_STATION*>(my_data->main_REC->getEqPointer("first"));
16
18
}
17
18
std::string command_ardu::execute(std::vector<std::string> &v, thread_data *my_data)
19
14
{
20
14
    std::string str_buf = " only for internal usage!";
21
14
    if (v.size() > 1){
22
14
        if(v[1] == "show"){
23
1
            RADIO_WEATHER_STATION* st = static_cast<RADIO_WEATHER_STATION*>(my_data->main_REC->getEqPointer("first"));
24
1
            str_buf = st->data.getDataString();
25
1
        }
26
14
        if(v[1] == "433MHz"){
27
13
            my_data->myEventHandler.run("433MHz")->addEvent("RFLink: "+v[2]);
28
13
            try {
29
13
                my_data->main_RFLink->
30
13
                        rflinkMAP[my_data->main_RFLink->getArgumentValueFromRFLinkMSG(v[2],
31
13
                        "ID")].counter();
32
13
                my_data->main_RFLink->
33
13
                        rflinkMAP[my_data->main_RFLink->getArgumentValueFromRFLinkMSG(v[2],
34
13
                        "ID")].msg = v[2];
35
13
            }
36
13
            catch(const std::string& e){
37
3
                std::cout << "wyjatek w szukaniu: " << e <<std::endl;
38
3
                pingAndOkRecv( my_data, v[2]);
39
3
            }
40
13
            //TODO add command
41
13
            try {
42
12
                if (m_mainRadioButton->getID() == my_data->main_RFLink->getArgumentValueFromRFLinkMSG(v[2],"ID") )
43
12
                {
44
6
                    my_data->main_iDomTools->button433mhzLockerPressed(m_mainRadioButton);
45
6
                }
46
12
            }
47
12
            catch (const std::string& e){ }
48
12
            try {
49
12
                if (m_mainWeatherStation->getID() == my_data->main_RFLink->getArgumentValueFromRFLinkMSG(v[2],"ID") )
50
12
                {
51
3
                    m_mainWeatherStation->data.putData(v[2]);
52
3
                }
53
12
            }
54
12
            catch (std::string& e){ }
55
12
        }
56
14
    }
57
14
    return str_buf;
58
14
}
59
60
std::string command_ardu::help()
61
2
{
62
2
    return " only for internal usege\n";
63
2
}
64
65
void command_ardu::pingAndOkRecv(thread_data *my_data, const std::string& s)
66
3
{
67
3
    if (s.find("OK;") != std::string::npos)
68
3
        my_data->main_RFLink->okTime = Clock::getUnixTime();
69
3
    else if (s.find("PONG;") != std::string::npos)
70
2
        my_data->main_RFLink->pingTime = Clock::getUnixTime();
71
3
    std::cout << "poing && ok recv " << s <<std::endl
72
3
              << " ok time: "<<my_data->main_RFLink->okTime<< std::endl
73
3
              << " ping time: "<<my_data->main_RFLink->pingTime<< std::endl;
74
3
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/command_big.cpp
Line
Count
Source
1
#include "command_big.h"
2
3
command_big::command_big(const std::string &name):command(name)
4
8
{
5
8
6
8
}
7
8
std::string command_big::execute(std::vector<std::string> &v, thread_data *my_data)
9
1
{
10
1
    std::string str_buf = "command big - wrong paramiter:\n "+ help();
11
1
    if (v.size() > 1){
12
1
        str_buf.erase();
13
55
        for (int i =0; i < std::stoi(v[1])-1; ++i){
14
54
            str_buf += "z";
15
54
        }
16
1
        str_buf += "Y";
17
1
    }
18
1
    return str_buf;
19
1
}
20
21
std::string command_big::help()
22
2
{
23
2
    return "big <number> - send big (number) data \n";
24
2
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/command_clock.cpp
Line
Count
Source
1
#include "command_clock.h"
2
#include "../../../src/functions/functions.h"
3
4
command_clock::command_clock(const std::string &name):command(name)
5
9
{
6
9
7
9
}
8
9
std::string command_clock::execute(std::vector<std::string> &v, thread_data *my_data)
10
2
{
11
2
    if (v.size() > 1){
12
1
        return "clock set "+ useful_F::send_to_arduino_clock(my_data,v[1]);
13
1
    }
14
2
    return "can not set clock";
15
2
}
16
17
std::string command_clock::help()
18
1
{
19
1
    return "clock <number/string> - put number/string (max 4 digits) to 7segment LCD\n";
20
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/command_cmd.cpp
Line
Count
Source
1
#include "command_cmd.h"
2
#include "../../../src/functions/functions.h"
3
4
command_cmd::command_cmd(const std::string &name):command(name)
5
9
{
6
9
7
9
}
8
9
std::string command_cmd::execute(std::vector<std::string> &v, thread_data *my_data)
10
2
{
11
2
    if (v.size() == 1){
12
1
        return "fifo file contain: "+ useful_F_libs::read_from_mkfifo(my_data->server_settings->omxplayerFile);
13
1
    }
14
2
    return "error: unknown parameter: "+v[1];
15
2
}
16
17
std::string command_cmd::help()
18
1
{
19
1
    return "cmd - read char prom cmd fifo file for unblock video player\n";
20
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/command_event.cpp
Line
Count
Source
1
#include "command_event.h"
2
3
command_event::command_event(const std::string &name) :command(name)
4
13
{
5
13
6
13
}
7
8
std::string command_event::execute(std::vector<std::string> &v, thread_data *my_data)
9
6
{
10
6
    if (v.size() == 1){
11
1
        return my_data->myEventHandler.getListPossibleEvents();
12
1
    }
13
6
    if (v.size() == 2){
14
1
        return my_data->myEventHandler.run(v[1])->getEvent();
15
1
    }
16
5
    if (v.size() == 3 && v[2]=="clear"){
17
1
        my_data->myEventHandler.run(v[1])->clearEvent();
18
1
        return "event " +v[1]+ " has been cleared!";
19
1
    }
20
4
    if (v.size() == 3 && v[2]=="intensity"){
21
1
        std::stringstream intensity;
22
1
        intensity << my_data->myEventHandler.run(v[1])->getLast1minNumberEvent();
23
1
        return "event " +v[1]+" "+ intensity.str() +" intensity per last minute!";
24
1
    }
25
3
    if (v.size() == 5 && v[2]=="clear"){
26
1
        unsigned int from = std::stoi(v[3]);
27
1
        unsigned int to = std::stoi(v[4]);
28
1
        my_data->myEventHandler.run(v[1])->clearEvent(from, to);
29
1
        return "event " +v[1]+ " has been cleared!";
30
1
    }
31
2
    return my_data->myEventHandler.help();
32
2
}
33
34
std::string command_event::help()
35
1
{
36
1
    std::stringstream help;
37
1
    help << "event- show actual event (all)" << std::endl;
38
1
    help << "event <name> - show one event" << std::endl;
39
1
    help << "event <name> clear - clear event <name>" << std::endl;
40
1
    help << "event <name> intensity - intensity per minute" <<std::endl;
41
1
    return help.str();
42
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/command_hello.cpp
Line
Count
Source
1
#include "command_hello.h"
2
3
command_hello::command_hello(const std::string &name):command(name)
4
8
{
5
8
}
6
7
command_hello::~command_hello()
8
8
{
9
8
}
10
11
std::string command_hello::execute(std::vector<std::string> &v, thread_data *my_data)
12
1
{
13
1
    return "\nHI You User!\n";
14
1
}
15
16
std::string command_hello::help()
17
1
{
18
1
    return "hello - send test message to server if connection is ok, the server response: \"HI!\"\n";
19
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/command_help.cpp
Line
Count
Source
1
#include "command_help.h"
2
#include <vector>
3
#include <algorithm>
4
5
command_help::command_help(const std::string &name):command(name)
6
10
{
7
10
}
8
9
std::string command_help::execute(std::vector<std::string> &v, thread_data *my_data)
10
3
{
11
3
    std::string result ="";
12
3
    if (v.size() ==2){
13
2
14
2
        if (my_data->commandMapPtr->find(v[1]) == my_data->commandMapPtr->end()){
15
1
            return "unknown command: "+ v[1]+" help note not found";
16
1
        }
17
2
        else{
18
1
            return my_data->commandMapPtr->find(v[1])->second->help();
19
1
        }
20
2
    }
21
3
    else
22
3
    {
23
23
        for( auto iter= my_data->commandMapPtr->begin();iter != my_data->commandMapPtr->end(); ++iter ) {
24
22
25
22
            result+= iter->second->help();
26
22
            result+= "------------------------------------\n";
27
22
        }
28
1
    }
29
3
    return result;
30
3
}
31
32
std::string command_help::help()
33
1
{
34
1
    return "help - show help for all command \nhelp <parameter> - show help for command\n";
35
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/command_idom.cpp
Line
Count
Source (jump to first uncovered line)
1
#include "command_idom.h"
2
#include "../../functions/functions.h"
3
4
command_iDom::command_iDom(const std::string &name):command(name)
5
27
{
6
27
}
7
8
std::string command_iDom::execute(std::vector<std::string> &v, thread_data *my_data)
9
30
{
10
30
    if (v.size()<2){
11
1
        return "need parameter!\n" + help();
12
1
    }
13
30
    if (v[1]=="speakers")
14
29
    {
15
3
        if (v[2] =="ON"){
16
1
            iDomTOOLS::turnOnSpeakers();
17
1
            return "speakers ON";
18
1
        }
19
3
        else if (v[2]=="OFF"){
20
1
            iDomTOOLS::turnOffSpeakers();
21
1
            return "speakers OFF";
22
1
        }
23
2
        else{
24
1
            return "unknow speakers action: "+v[2];
25
1
        }
26
3
    }
27
29
    else if (v[1]=="sunset"){
28
1
        return my_data->main_iDomTools->getSunset(true);
29
1
    }
30
26
    else if (v[1]=="sunrise"){
31
1
        return my_data->main_iDomTools->getSunrise(true);
32
1
    }
33
25
    else if (v[1]=="day" && v[2]=="lenght"){
34
1
        return my_data->main_iDomTools->getDayLenght(true);
35
1
    }
36
24
    else if (v[1]=="sun"){
37
1
        std::string ret;
38
1
        ret = my_data->main_iDomTools->getSunrise(true);
39
1
        ret.append("\n");
40
1
        ret.append(my_data->main_iDomTools->getSunset(true));
41
1
        ret.append("\n");
42
1
        ret.append(my_data->main_iDomTools->getDayLenght(true));
43
1
        ret.append("\n");
44
1
        return ret;
45
1
    }
46
23
    else if (v[1]=="sysinfo"){
47
1
        return my_data->main_iDomTools->getSystemInfo();
48
1
    }
49
22
    else if (v[1]=="temperature"){
50
2
        if ( v.size() < 3){
51
1
            return my_data->main_iDomTools->getTemperatureString();
52
1
        }
53
2
        else {
54
1
            if (v[2] == "stats"){
55
1
                std::string ret;
56
1
                try{
57
1
                 ret = my_data->main_iDomTools->getThermoStats(v[3]);
58
1
                }
59
1
                catch (std::string& obj){
60
1
                    ret = obj +" "+v[3];
61
1
                }
62
1
               return ret;
63
1
            }
64
1
        }
65
2
    }
66
21
    else if (v[1]=="text"){
67
1
        return my_data->main_iDomTools->getTextToSpeach();
68
1
    }
69
19
    else if (v[1] == "lock"){
70
1
        my_data->main_iDomTools->lockHome();
71
1
        return "hous locked";
72
1
    }
73
18
    else if (v[1] == "unlock"){
74
1
        my_data->main_iDomTools->unlockHome();
75
1
        return "hous unlocked";
76
1
    }
77
17
    else if (v[1]=="LED"){
78
2
        if (v.size() != 7){
79
2
            if (v[2]=="OFF"){
80
1
                return my_data->main_iDomTools->ledOFF();
81
1
            }
82
2
            else if(v[2] == "set"){
83
0
               return my_data->main_iDomTools->ledOn(
84
0
                            my_data->ptr_pilot_led->colorLED[2],
85
0
                            std::stoi(v[3]),
86
0
                            std::stoi(v[4])
87
0
                            );
88
0
            }
89
1
            else{
90
1
                return "need more parameter from-to-R-G-B";
91
1
            }
92
2
        }
93
2
        else {
94
0
            LED_Strip strip(v[2],v[3],v[4],v[5],v[6]);
95
0
            return my_data->main_iDomTools->ledOn(strip);
96
0
        }
97
2
    }
98
16
    else if (v[1]=="say"){
99
1
        if (v.size() > 3){
100
1
            std::vector<std::string> vTTS ={ my_data->main_iDomTools->getTextToSpeach()};
101
1
            my_data->main_iDomTools->textToSpeach(&vTTS);
102
1
            return "sad";
103
1
        }
104
1
    }
105
14
    else if (v[1]=="smog"){
106
1
        return my_data->main_iDomTools->getSmog()+" mg/m^3";
107
1
    }
108
13
    else if (v[1]=="230V"){
109
3
        if (v.size() > 2 && v[2]=="ON"){
110
1
            my_data->main_iDomTools->turnOnPrinter();
111
1
            return "230V ON";
112
1
        }
113
3
        else if(v.size() > 2 && v[2]=="OFF"){
114
1
            my_data->main_iDomTools->turnOffPrinter();
115
1
            return "230V OFF";
116
1
        }
117
2
        else {
118
1
            return "wrong paramiter";
119
1
        }
120
3
    }
121
12
    else if (v[1]=="wifi"){
122
1
        std::string readBuffer = useful_F_libs::httpPost("http://cyniu88.no-ip.pl/cgi-bin/kto_wifi.sh",10);
123
1
        return readBuffer;
124
1
    }
125
9
    else if (v[1]=="lightning"){
126
1
        std::stringstream readBuffer;
127
1
        readBuffer << my_data->main_iDomTools->getLightningStruct().data.str();
128
1
        readBuffer << std::endl;
129
1
        readBuffer << "bool: " << my_data->main_iDomTools->getLightningStruct().riseAlarm;
130
1
        readBuffer <<std::endl <<" time: ";
131
1
        readBuffer << Clock::getTime().getString();
132
1
        return readBuffer.str();
133
1
    }
134
8
    else if (v[1]=="kill"){
135
0
136
0
        if (v[2]=="thread"){
137
0
            my_data->main_THREAD_arr->at(std::stoi(v[3]) ).thread.~thread();
138
0
            return "done!";
139
0
        }
140
0
    }
141
7
    else if (v[1]=="facebook"){
142
0
        std::string msg;
143
0
        for (unsigned int i = 2; i < v.size(); ++i){
144
0
            msg+=" ";
145
0
            msg+=v[i];
146
0
        }
147
0
        return my_data->main_iDomTools->postOnFacebook(msg);
148
0
    }
149
7
    else if (v[1]=="viber"){
150
0
        std::string msg;
151
0
        for (unsigned int i = 2; i < v.size(); ++i){
152
0
            msg+=" ";
153
0
            msg+=v[i];
154
0
        }
155
0
        STATE stMSG = my_data->main_iDomTools->sendViberMsgBool(msg, my_data->server_settings->viberReceiver.at(0),
156
0
                                                     my_data->server_settings->viberSender);
157
0
        if(stMSG == STATE::SEND_OK){
158
0
            return "wiadomosc wyslana poprawnie";
159
0
        }
160
0
        else{
161
0
            return "blad wysylania wiadomosci - sprawdz logi";
162
0
        }
163
0
    }
164
7
    else if (v[1] == "camera"){
165
3
166
3
        if (v.size() < 4){
167
1
            return "not enough parameters";
168
1
        }
169
3
        if (v[2]=="LED" && v[3] == "ON"){
170
1
            my_data->main_iDomTools->cameraLedON(my_data->server_settings->cameraLedON);
171
1
        }
172
2
        else if (v[2]=="LED" && v[3] == "OFF"){
173
1
            my_data->main_iDomTools->cameraLedOFF(my_data->server_settings->cameraLedOFF);
174
1
        }
175
2
        return "led DONE";
176
3
    }
177
7
    else if (v[1]=="weather"){
178
0
179
0
        if (v.size() < 4){
180
0
            return "not enough parameters";
181
0
        }
182
0
        std::string tempHTML = my_data->main_iDomTools->getWeatherEvent(v[2],std::stoi(v[3]));
183
0
        return useful_F_libs::removeHtmlTag(tempHTML);
184
0
    }
185
4
    else if (v[1] == "KODI"){
186
3
        return my_data->main_iDomTools->startKodi_Thread();
187
3
    }
188
4
    else if (v[1]=="alarm"){
189
0
190
0
        if (v.size() < 3){
191
0
            return "not enough parameters";
192
0
        }
193
0
        if (v[2] == "OFF"){
194
0
            my_data->alarmTime.state = STATE::DEACTIVE;
195
0
            my_data->main_iDomStatus->setObjectState("alarm", my_data->alarmTime.state);
196
0
            my_data->main_iDomTools->saveState_iDom();
197
0
            return "alarm clock has been deactivated";
198
0
        }
199
0
        else if (v[2] == "GET"){
200
0
            return my_data->alarmTime.time.getString();
201
0
        }
202
0
        else if (v[2] == "SET" && v.size() == 5){
203
0
            if (v[3] == "from")
204
0
            {
205
0
                my_data->alarmTime.fromVolume = std::stoi(v[4]);
206
0
            }
207
0
            else if (v[3] == "to")
208
0
            {
209
0
                my_data->alarmTime.toVolume = std::stoi(v[4]);
210
0
            }
211
0
            else if (v[3] == "radio")
212
0
            {
213
0
                my_data->alarmTime.radioID = std::stoi(v[4]);
214
0
            }
215
0
            std::stringstream ret;
216
0
            ret << "The values has beedn set:" << std::endl;
217
0
            ret << "From Value: " << my_data->alarmTime.fromVolume << std::endl;
218
0
            ret << "To Value: " << my_data->alarmTime.toVolume << std::endl;
219
0
            ret << "Radio ID: " << my_data->alarmTime.radioID << std::endl;
220
0
            my_data->main_iDomTools->saveState_iDom();
221
0
            return ret.str();
222
0
        }
223
0
        else if (v[2] == "ON" && v.size() > 3){
224
0
            my_data->alarmTime.time = Clock(v[3]);
225
0
            my_data->alarmTime.state = STATE::ACTIVE;
226
0
            my_data->main_iDomStatus->setObjectState("alarm", my_data->alarmTime.state);
227
0
            my_data->main_iDomTools->saveState_iDom();
228
0
            return "alarm clock has been activated";
229
0
        }
230
0
    }
231
29
    return "iDom - unknown parameter: "+ v[1];
232
29
}
233
234
std::string command_iDom::help()
235
3
{
236
3
    std::stringstream help;
237
3
    help << "iDom - for control smart home" << std::endl;
238
3
    help << "iDom speakers ON/OFF - to on or off speakers" << std::endl;
239
3
    help << "iDom 230v ON/OFF     - to on or off printers" << std::endl;
240
3
    help << "iDom sunset/sunrise/day lenght - to show those parameters" << std::endl;
241
3
    help << "iDom sun        - get sunrise, sunset and day lenght" << std::endl;
242
3
    help << "iDom sysinfo    - get system info" << std::endl;
243
3
    help << "iDom text       - get text to speach" << std::endl;
244
3
    help << "iDom say <text> - say standatrd info or <text>" << std::endl;
245
3
    help << "iDom sms <text> - send sms<text>" << std::endl;
246
3
    help << "iDom LED <FROM> <TO> <R> <G> <B> - set RGB LED strip" << std::endl;
247
3
    help << "iDom LED OFF    - led off" << std::endl;
248
3
    help << "iDom LED set <from> <to> - set green led from to" << std::endl;
249
3
    help << "iDom temperature - get temperature from all termomether" << std::endl;
250
3
    help << "iDom temperature stats <name> - get temperature stats from termomether <name>" << std::endl;
251
3
    help << "iDom smog       - get current SMOG level (KRAKOW)" << std::endl;
252
3
    help << "iDom kill thread <ID>  - kill thread but denger!" << std::endl;
253
3
    help << "iDom camera LED ON/OFF - LED camera work" << std::endl;
254
3
    help << "iDom facebook ... - post on facebook wall" << std::endl;
255
3
    help << "iDom viber ...   - send viber msg" << std::endl;
256
3
    help << "iDom weather <city> <radius> - get weather alert" << std::endl;
257
3
    help << "iDom lightning  - get lightning alert" << std::endl;
258
3
    help << "iDom alarm ON/OFF hh:mm - set larm clock" << std::endl;
259
3
    help << "iDom alarm SET from/to/radio <value> - set larm clock" << std::endl;
260
3
    help << "iDom alarm GET - get alarm time" << std::endl;
261
3
    help << "iDom lock   - lock home" << std::endl;
262
3
    help << "iDom unlock - unlock home" << std::endl;
263
3
    help << "iDom KODI - start KODI smart TV" << std::endl;
264
3
    help << "iDom wifi - show all wifi client" << std::endl;
265
3
    return help.str();
266
3
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/command_ip.cpp
Line
Count
Source
1
#include "command_ip.h"
2
3
command_ip::command_ip(const std::string &name):command(name)
4
8
{
5
8
}
6
7
std::string command_ip::execute(std::vector<std::string> &v, thread_data *my_data)
8
1
{
9
1
    return "iDom server IP: " +my_data->server_settings->SERVER_IP;
10
1
}
11
12
std::string command_ip::help()
13
1
{
14
1
    return "ip - show server IP address\n";
15
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/command_log.cpp
Line
Count
Source
1
#include "command_log.h"
2
3
command_log::command_log(const std::string &name):command(name)
4
8
{
5
8
}
6
7
std::string command_log::execute(std::vector<std::string> &v, thread_data *my_data)
8
8
{
9
8
    std::string msg;
10
16
    for (unsigned int i = 2; i < v.size(); ++i)
11
8
    {
12
8
        msg+=" ";
13
8
        msg+=v[i];
14
8
    }
15
8
    log_file_mutex.mutex_lock();
16
8
    log_file_cout <<"USER:- " << logLevel(v[1]) << msg <<std::endl;;
17
8
    log_file_mutex.mutex_unlock();
18
8
    return "DONE!";
19
8
}
20
21
std::string command_log::help()
22
1
{
23
1
    std::stringstream help;
24
1
    help << "log <logLevel> \"***TXT***\"- add *** to iDom logfile" << std::endl;
25
1
    return help.str();
26
1
}
27
28
logger_level command_log::logLevel(const std::string &level)
29
8
{
30
8
    if (level == "VERBOSE"){
31
1
        return VERBOSE;
32
1
    }
33
8
    else if (level == "DEBUG"){
34
1
        return DEBUG;
35
1
    }
36
7
    else if (level == "INFO"){
37
1
        return INFO;
38
1
    }
39
6
    else if (level == "WARNING"){
40
1
        return WARNING;
41
1
    }
42
5
    else if (level == "ERROR"){
43
1
        return ERROR;
44
1
    }
45
4
    else if (level == "FATAL"){
46
1
        return FATAL;
47
1
    }
48
3
    else if (level == "CRITICAL"){
49
1
        return CRITICAL;
50
1
    }
51
8
puts ("nie mam co wysetlic wale verbose");
52
1
        return VERBOSE;
53
8
54
8
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_show_BT.cpp
Line
Count
Source
1
#include "../command_show.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_show_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_show_Class_fixture()
8
9
    {
9
9
10
9
    }
11
12
protected:
13
    std::unique_ptr<command_show> test_command_show;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
17
9
    {
18
9
        iDomTOOLS_ClassTest::SetUp();
19
9
        test_command_show = std::make_unique <command_show> ("show");
20
9
    }
21
22
    void TearDown() final
23
9
    {
24
9
        iDomTOOLS_ClassTest::TearDown();
25
9
    }
26
};
27
28
TEST_F(command_show_Class_fixture, wrongParameter)
29
1
{
30
1
    test_v.push_back("show");
31
1
    test_v.push_back("t");
32
1
    auto ret = test_command_show->execute(test_v,&test_my_data);
33
1
    EXPECT_STREQ(ret.c_str(), "wrong parameter: t");
34
1
}
35
36
TEST_F(command_show_Class_fixture, unknownParameter)
37
1
{
38
1
    test_v.push_back("show");
39
1
    auto ret = test_command_show->execute(test_v,&test_my_data);
40
1
    EXPECT_STREQ(ret.c_str(), "show what?");
41
1
}
42
43
TEST_F(command_show_Class_fixture, showThreadAll)
44
1
{
45
1
    std::array<Thread_array_struc, iDomConst::MAX_CONNECTION> threadArray;
46
1
47
1
    threadArray[1].thread_ID = std::this_thread::get_id();
48
1
    threadArray[1].thread_name = "thread1 test1";
49
1
    threadArray[1].thread_socket = 1;
50
1
    threadArray[2].thread_ID = std::this_thread::get_id();
51
1
    threadArray[2].thread_name = "thread1 test2";
52
1
    threadArray[2].thread_socket = 2;
53
1
54
1
    test_my_data.main_THREAD_arr = &threadArray;
55
1
56
1
    test_v.push_back("show");
57
1
    test_v.push_back("thread");
58
1
    test_v.push_back("all");
59
1
    auto ret = test_command_show->execute(test_v,&test_my_data);
60
1
    EXPECT_THAT(ret, testing::HasSubstr("socket: 2"));
61
1
}
62
63
TEST_F(command_show_Class_fixture, showThread)
64
1
{
65
1
    std::array<Thread_array_struc, iDomConst::MAX_CONNECTION> threadArray;
66
1
67
1
    threadArray[1].thread_ID = std::this_thread::get_id();
68
1
    threadArray[1].thread_name = "thread1 test1";
69
1
    threadArray[1].thread_socket = 1;
70
1
    threadArray[2].thread_ID = std::this_thread::get_id();
71
1
    threadArray[2].thread_name = "thread1 test2";
72
1
    threadArray[2].thread_socket = 2;
73
1
74
1
    test_my_data.main_THREAD_arr = &threadArray;
75
1
76
1
    test_v.push_back("show");
77
1
    test_v.push_back("thread");
78
1
    test_v.push_back("2");
79
1
    auto ret = test_command_show->execute(test_v,&test_my_data);
80
1
    EXPECT_THAT(ret, testing::HasSubstr("socket: 2"));
81
1
}
82
83
TEST_F(command_show_Class_fixture, showThreadNoId)
84
1
{
85
1
    test_v.push_back("show");
86
1
    test_v.push_back("thread");
87
1
    auto ret = test_command_show->execute(test_v,&test_my_data);
88
1
    EXPECT_STREQ(ret.c_str(), "No ID");
89
1
}
90
91
TEST_F(command_show_Class_fixture, showLog)
92
1
{
93
1
    test_v.push_back("show");
94
1
    test_v.push_back("log");
95
1
    auto ret = test_command_show->execute(test_v,&test_my_data);
96
1
    EXPECT_STREQ(ret.c_str(), "return test in l_send_file()");
97
1
}
98
99
TEST_F(command_show_Class_fixture, showLogNoInfo)
100
1
{
101
1
    test_v.push_back("show");
102
1
    test_v.push_back("log");
103
1
    test_v.push_back("no");
104
1
    test_v.push_back("INFO");
105
1
    auto ret = test_command_show->execute(test_v,&test_my_data);
106
1
    EXPECT_STREQ(ret.c_str(), "return test in l_send_file()");
107
1
}
108
109
TEST_F(command_show_Class_fixture, showLogInfo)
110
1
{
111
1
    test_v.push_back("show");
112
1
    test_v.push_back("log");
113
1
    test_v.push_back("INFO");
114
1
    auto ret = test_command_show->execute(test_v,&test_my_data);
115
1
    EXPECT_STREQ(ret.c_str(), "return test in l_send_file()");
116
1
}
117
118
TEST_F(command_show_Class_fixture, showLogFakeInfo)
119
1
{
120
1
    test_v.push_back("show");
121
1
    test_v.push_back("log");
122
1
    test_v.push_back("fake");
123
1
    test_v.push_back("INFO");
124
1
    auto ret = test_command_show->execute(test_v,&test_my_data);
125
1
    EXPECT_STREQ(ret.c_str(), "do you mean : show log no <string>?");
126
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/command_mpd.cpp
Line
Count
Source
1
#include "command_mpd.h"
2
#include "../../blockQueue/blockqueue.h"
3
#include "../../functions/functions.h"
4
5
command_mpd::command_mpd(const std::string &name) :command(name)
6
16
{
7
16
}
8
9
std::string command_mpd::execute(std::vector<std::string> &v, thread_data *my_data)
10
14
{
11
14
    std::string str_buf;
12
14
13
14
    if (v[1]=="start")
14
14
    {
15
2
        if (v.size()>2)
16
2
        {
17
1
            int id = std::stoi(v[2]);
18
1
            if (id > 0)
19
1
            {
20
1
                iDomTOOLS::MPD_play(my_data,id);
21
1
                useful_F::sleep(1);
22
1
                str_buf = my_data->ptr_MPD_info->songList[id-1];
23
1
            }
24
1
        }
25
2
        else
26
2
        {
27
1
            iDomTOOLS::MPD_play(my_data);
28
1
            useful_F::sleep(1);
29
1
            str_buf=my_data->ptr_MPD_info->title;
30
1
        }
31
2
        my_data->main_iDomTools->saveState_iDom();
32
2
    }
33
14
    else if (v[1]=="stop")
34
12
    {
35
1
        iDomTOOLS::MPD_stop();
36
1
        str_buf="stoped!";
37
1
        my_data->main_iDomTools->saveState_iDom();
38
1
    }
39
12
    else if (v[1]=="next")
40
11
    {
41
1
        iDomTOOLS::MPD_next();
42
1
        useful_F::sleep(1);
43
1
        str_buf = my_data->ptr_MPD_info->radio + " : "+ my_data->ptr_MPD_info->title;
44
1
    }
45
11
    else if (v[1]=="prev")
46
10
    {
47
1
        iDomTOOLS::MPD_prev();
48
1
        useful_F::sleep(1);
49
1
        str_buf=my_data->ptr_MPD_info->radio+ " : "+ my_data->ptr_MPD_info->title;
50
1
    }
51
10
    else if (v[1]=="pause")
52
9
    {
53
1
        iDomTOOLS::MPD_pause();
54
1
        str_buf="paused!";
55
1
    }
56
9
    else if (v[1]=="volume")
57
8
    {
58
4
        if (v[2]=="up")
59
4
        {
60
1
            iDomTOOLS::MPD_volumeUp();
61
1
        }
62
4
        else if (v[2]=="down")
63
3
        {
64
1
            iDomTOOLS::MPD_volumeDown();
65
1
        }
66
3
        else
67
3
        {
68
2
            int vol = std::stoi(v[2]);
69
2
            if (vol >0 && vol <100)
70
2
            {
71
1
                iDomTOOLS::MPD_volumeSet(my_data,vol);
72
1
            }
73
2
        }
74
4
        //sleep(1);
75
4
        str_buf=std::to_string(my_data->ptr_MPD_info->volume);
76
4
    }
77
8
    else if (v[1]=="get")
78
4
    {
79
2
        if(v[2]=="volume")
80
2
        {
81
1
            str_buf=std::to_string(my_data->ptr_MPD_info->volume);
82
1
        }
83
2
        else if (v[2]=="info")
84
1
        {
85
1
            str_buf = my_data->ptr_MPD_info->radio + " : "+ my_data->ptr_MPD_info->title;
86
1
        }
87
2
    }
88
4
    else if (v[1]=="list")
89
2
    {
90
1
        for (auto i : my_data->ptr_MPD_info->songList)
91
3
            str_buf += i+"\n";
92
1
    }
93
2
    else
94
2
    {
95
1
        str_buf = "unknown parameter " + v[1];
96
1
    }
97
14
    return str_buf;
98
14
}
99
100
std::string command_mpd::help()
101
1
{
102
1
    std::stringstream help;
103
1
    help << "MPD - for control music player:" << std::endl;
104
1
    help << "parameter:" << std::endl;
105
1
    help << "\tstart - play music" << std::endl;
106
1
    help << "\tstop  - stop music" << std::endl;
107
1
    help << "\tpause - pause music" << std::endl;
108
1
    help << "\tnext  - next song" << std::endl;
109
1
    help << "\tprev  - previous song" << std::endl;
110
1
    help << "\tlist  - show playlist" << std::endl;
111
1
    help << "\tget volume - get volume %" << std::endl;
112
1
    help << "\tget info - get info about current song" << std::endl;
113
1
    help << "\tvolume up/down - increase/decrease volume 1%" << std::endl;
114
1
    return help.str();
115
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/command_ok.cpp
Line
Count
Source
1
#include "command_ok.h"
2
3
command_ok::command_ok(const std::string &name):command(name)
4
8
{
5
8
}
6
7
std::string command_ok::execute(std::vector<std::string> &v, thread_data *my_data)
8
2
{
9
2
    return "\nEND\n";
10
2
}
11
12
std::string command_ok::help()
13
2
{
14
2
    return "ok - confirmation msg server response: END \n";
15
2
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_sleep_BT.cpp
Line
Count
Source
1
#include "../command_sleep.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_sleep_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_sleep_Class_fixture()
8
5
    {
9
5
10
5
    }
11
12
protected:
13
    std::unique_ptr<command_sleep> test_command_sleep;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
17
5
    {
18
5
        iDomTOOLS_ClassTest::SetUp();
19
5
        test_command_sleep = std::make_unique <command_sleep> ("sleep");
20
5
    }
21
22
    void TearDown() final
23
5
    {
24
5
        iDomTOOLS_ClassTest::TearDown();
25
5
    }
26
};
27
28
TEST_F(command_sleep_Class_fixture, sleep)
29
1
{
30
1
    test_my_data.sleeper = 88;
31
1
32
1
    test_v.push_back("sleep");
33
1
    auto ret = test_command_sleep->execute(test_v,&test_my_data);
34
1
    EXPECT_STREQ(ret.c_str(), "sleep set to: 88");
35
1
}
36
37
TEST_F(command_sleep_Class_fixture, sleepFakeParam)
38
1
{
39
1
    test_my_data.sleeper = 88;
40
1
41
1
    test_v.push_back("sleep");
42
1
    test_v.push_back("fake");
43
1
    auto ret = test_command_sleep->execute(test_v,&test_my_data);
44
1
    EXPECT_STREQ(ret.c_str(), "internal error");
45
1
}
46
47
TEST_F(command_sleep_Class_fixture, sleepFakeParam2)
48
1
{
49
1
    test_my_data.sleeper = 88;
50
1
51
1
    test_v.push_back("sleep");
52
1
    test_v.push_back("fake");
53
1
    test_v.push_back("fake2");
54
1
    auto ret = test_command_sleep->execute(test_v,&test_my_data);
55
1
    EXPECT_STREQ(ret.c_str(), "wrong parametr fake");
56
1
}
57
58
TEST_F(command_sleep_Class_fixture, sleepSetNoIntiger)
59
1
{
60
1
    test_my_data.sleeper = 88;
61
1
62
1
    test_v.push_back("sleep");
63
1
    test_v.push_back("set");
64
1
    test_v.push_back("fake2");
65
1
    auto ret = test_command_sleep->execute(test_v,&test_my_data);
66
1
    EXPECT_STREQ(ret.c_str(), "system need intiger > 0 not: fake2");
67
1
}
68
69
TEST_F(command_sleep_Class_fixture, sleepSet)
70
1
{
71
1
    std::array<Thread_array_struc, iDomConst::MAX_CONNECTION> threadArray;
72
1
73
1
    threadArray[1].thread_ID = std::this_thread::get_id();
74
1
    threadArray[1].thread_name = "thread1 test1";
75
1
    threadArray[1].thread_socket = 1;
76
1
    threadArray[2].thread_ID = std::this_thread::get_id();
77
1
    threadArray[2].thread_name = "thread1 test2";
78
1
    threadArray[2].thread_socket = 2;
79
1
80
1
    test_my_data.main_THREAD_arr = &threadArray;
81
1
82
1
    test_v.push_back("sleep");
83
1
    test_v.push_back("set");
84
1
    test_v.push_back("2");
85
1
    auto ret = test_command_sleep->execute(test_v,&test_my_data);
86
1
    EXPECT_STREQ(ret.c_str(), "DONE - Sleep MPD STARTED");
87
1
    sleep(1);
88
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/command_program.cpp
Line
Count
Source
1
#include "command_program.h"
2
#include "../../functions/functions.h"
3
#include "../../433MHz/RFLink/rflinkhandler.h"
4
5
command_program::command_program(const std::string &name):command(name)
6
16
{
7
16
}
8
9
std::string command_program::execute(std::vector<std::string> &v, thread_data *my_data)
10
10
{
11
10
    std::string ret = help();
12
10
    if (v.size() <2 )
13
10
    {
14
1
        return "what?\n" + help();
15
1
    }
16
10
    if (v[1] == "stop")
17
9
    {
18
2
        std::string s ="close server";
19
2
        useful_F::send_to_arduino_clock(my_data, "STOP");
20
2
        iDomTOOLS::MPD_stop();
21
2
        my_data->iDomProgramState = iDomStateEnum::CLOSE;
22
2
        my_data->main_iDomTools->saveState_iDom();
23
2
        throw s;
24
2
    }
25
9
    if (v.size() < 3 )
26
7
    {
27
1
        return "add more paramiters";
28
1
    }
29
7
    if(v[1] == "reload" && v[2] == "soft"){
30
1
        std::string s ="close server";
31
1
        useful_F::send_to_arduino_clock(my_data, "RELO");
32
1
        iDomTOOLS::MPD_stop();
33
1
        my_data->iDomProgramState = iDomStateEnum::RELOAD;
34
1
        my_data->main_iDomTools->saveState_iDom();
35
1
        throw s;
36
1
    }
37
6
    else if(v[1] == "reload" && v[2] == "hard")
38
5
    {
39
1
        std::string s ="close server";
40
1
        useful_F::send_to_arduino_clock(my_data, "UPAD");
41
1
        iDomTOOLS::MPD_stop();
42
1
        my_data->iDomProgramState = iDomStateEnum::HARD_RELOAD;
43
1
        my_data->main_iDomTools->saveState_iDom();
44
1
        throw s;
45
1
    }
46
5
    else if(v[1] == "clear" && v[2] == "ram")
47
4
    {
48
1
        useful_F::runLinuxCommand("sync; echo 3 > /proc/sys/vm/drop_caches");
49
1
        ret = "ram has beed freed";
50
1
    }
51
4
    else if(v[1] == "debuge" && v[2] == "variable")
52
3
    {
53
1
        std::stringstream r;
54
1
       r << "my_data->alarmTime.fromVolume \t" << my_data->alarmTime.fromVolume <<std::endl;
55
1
        r << "my_data->alarmTime.radioID \t" << my_data->alarmTime.radioID <<std::endl;
56
1
        r << "my_data->alarmTime.state \t" << stateToString( my_data->alarmTime.state) <<std::endl;
57
1
        r << "my_data->alarmTime.time \t" << my_data->alarmTime.time.getString() <<std::endl;
58
1
        r << "my_data->alarmTime.toVolume \t" << my_data->alarmTime.toVolume <<std::endl;
59
1
        r << std::endl;
60
1
        r << "my_data->encriptionKey \t" << my_data->encriptionKey <<std::endl;
61
1
        r << std::endl;
62
1
        r << "my_data->server_settings->BaudRate \t" << my_data->server_settings->BaudRate <<std::endl;
63
1
        r << "my_data->server_settings->cameraLedOFF \t" << my_data->server_settings->cameraLedOFF <<std::endl;
64
1
        r << "my_data->server_settings->cameraLedON \t" << my_data->server_settings->cameraLedON <<std::endl;
65
1
        r << "my_data->server_settings->cameraURL \t" << my_data->server_settings->cameraURL <<std::endl;
66
1
        r << "my_data->server_settings->encrypted \t" << my_data->server_settings->encrypted <<std::endl;
67
1
        r << "my_data->server_settings->facebookAccessToken \t" << my_data->server_settings->facebookAccessToken <<std::endl;
68
1
        r << "my_data->server_settings->ftpServer.URL \t" << my_data->server_settings->ftpServer.URL <<std::endl;
69
1
        r << "my_data->server_settings->ftpServer.user \t" << my_data->server_settings->ftpServer.user <<std::endl;
70
1
        r << "my_data->server_settings->ID_server \t" << my_data->server_settings->ID_server <<std::endl;
71
1
        r << "my_data->server_settings->lightningApiURL \t" << my_data->server_settings->lightningApiURL <<std::endl;
72
1
        r << "my_data->server_settings->MENU_PATH \t" << my_data->server_settings->MENU_PATH<<std::endl;
73
1
        r << "my_data->server_settings->MOVIES_DB_PATH \t" << my_data->server_settings->MOVIES_DB_PATH<<std::endl;
74
1
        r << "my_data->server_settings->MPD_IP \t" << my_data->server_settings->MPD_IP<<std::endl;
75
1
        r << "my_data->server_settings->omxplayerFile \t" << my_data->server_settings->omxplayerFile<<std::endl;
76
1
        r << "my_data->server_settings->PORT \t" << my_data->server_settings->PORT<<std::endl;
77
1
        r << "my_data->server_settings->portRS232 \t" << my_data->server_settings->portRS232<<std::endl;
78
1
        r << "my_data->server_settings->portRS232_clock \t" << my_data->server_settings->portRS232_clock<<std::endl;
79
1
        r << "my_data->server_settings->radio433MHzConfigFile \t" << my_data->server_settings->radio433MHzConfigFile<<std::endl;
80
1
        r << "my_data->server_settings->RFLinkBaudRate \t" << my_data->server_settings->RFLinkBaudRate<<std::endl;
81
1
        r << "my_data->server_settings->RFLinkPort \t" << my_data->server_settings->RFLinkPort<<std::endl;
82
1
        r << "my_data->server_settings->saveFilePath \t" << my_data->server_settings->saveFilePath<<std::endl;
83
1
        r << "my_data->server_settings->SERVER_IP \t" << my_data->server_settings->SERVER_IP<<std::endl;
84
1
        r << "my_data->server_settings->THREAD_CRON \t" << my_data->server_settings->THREAD_CRON<<std::endl;
85
1
        r << "my_data->server_settings->THREAD_DUMMY \t" << my_data->server_settings->THREAD_DUMMY<<std::endl;
86
1
        r << "my_data->server_settings->THREAD_IRDA \t" << my_data->server_settings->THREAD_IRDA<<std::endl;
87
1
        r << "my_data->server_settings->THREAD_MPD \t" << my_data->server_settings->THREAD_MPD<<std::endl;
88
1
        r << "my_data->server_settings->THREAD_RS232 \t" << my_data->server_settings->THREAD_RS232<<std::endl;
89
1
        r << "my_data->server_settings->TS_KEY \t" << my_data->server_settings->TS_KEY<<std::endl;
90
1
        r << "my_data->server_settings->viberAvatar \t" << my_data->server_settings->viberAvatar<<std::endl;
91
1
        r << "my_data->server_settings->viberReceiver.at(0) \t" << my_data->server_settings->viberReceiver.at(0)<<std::endl;
92
1
        r << "my_data->server_settings->viberSender \t" << my_data->server_settings->viberSender<<std::endl;
93
1
        r << "my_data->server_settings->viberToken \t" << my_data->server_settings->viberToken<<std::endl;
94
1
        r << "my_data->server_settings->v_delay \t" << my_data->server_settings->v_delay<<std::endl;
95
1
        r << std::endl;
96
1
        r << "my_data->server_settings->sleeper \t" << my_data->sleeper<<std::endl;
97
1
        r << std::endl;
98
1
        r << "my_data->iDomProgramState \t" << static_cast<int>(my_data->iDomProgramState)<<std::endl;
99
1
        r << std::endl;
100
1
        r << "my_data->main_iDomStatus \t" << my_data->main_iDomStatus->getAllObjectsStateString()<<std::endl;
101
1
        r << std::endl;
102
1
        r << "my_data->idom_all_state.houseState \t" <<stateToString(my_data->idom_all_state.houseState)<<std::endl;
103
1
        r << std::endl;
104
1
        r << "my_data->now_time \t" << my_data->now_time<<std::endl;
105
1
        r << "my_data->start - time \t" << my_data->start<<std::endl;
106
1
        r << std::endl;
107
1
        r << "my_data->pointer.ptr_buf \t" << my_data->pointer.ptr_buf<<std::endl;
108
1
        r << "my_data->pointer.ptr_who \t" << my_data->pointer.ptr_who<<std::endl;
109
1
110
1
        r << std::endl;
111
1
        r << "my_data->ptr_MPD_info->artist \t" << my_data->ptr_MPD_info->artist<<std::endl;
112
1
        r << "my_data->ptr_MPD_info->currentSongID \t" << my_data->ptr_MPD_info->currentSongID<<std::endl;
113
1
        r << "my_data->ptr_MPD_info->isPlay \t" << my_data->ptr_MPD_info->isPlay<<std::endl;
114
1
        r << "my_data->ptr_MPD_info->radio \t" << my_data->ptr_MPD_info->radio<<std::endl;
115
1
        r << "my_data->ptr_MPD_info->songList.at(0) \t" << my_data->ptr_MPD_info->songList.at(0)<<std::endl;
116
1
        r << "my_data->ptr_MPD_info->title \t" << my_data->ptr_MPD_info->title<<std::endl;
117
1
        r << "my_data->ptr_MPD_info->volume \t" << my_data->ptr_MPD_info->volume<<std::endl;
118
1
119
1
        r << std::endl;
120
1
        r << "my_data->main_RFLink->okTime \t" << my_data->main_RFLink->okTime<<std::endl;
121
1
        r << "my_data->main_RFLink->pingTime \t" << my_data->main_RFLink->pingTime<<std::endl;
122
1
123
1
        r << std::endl;
124
1
        r << "my_data->mainLCD-> \t" << my_data->mainLCD->getData() <<std::endl;
125
1
126
1
        r << "END.";
127
1
        ret = r.str();
128
1
    }
129
3
    else if(v[1] == "raspberry")
130
2
    {
131
1
        int i = useful_F::runLinuxCommand(v[2].c_str());
132
1
        ret = "command done with exitcode: " + std::to_string(i);
133
1
    }
134
2
    else
135
2
    {
136
1
        ret = " what? - "+ v[1];
137
1
    }
138
6
    return ret;
139
6
}
140
141
std::string command_program::help()
142
12
{
143
12
    std::stringstream help;
144
12
    help << "program stop - close iDom server"<< std::endl;
145
12
    help << "program reload soft - reload iDom server" << std::endl;
146
12
    help << "program reload hard - reload iDom server" << std::endl;
147
12
    help << "program clear ram   - reload iDom server" << std::endl;
148
12
    help << "program debuge variable - show value iDom server variable" << std::endl;
149
12
    help << "program raspberry <command> - put command to raspberry " << std::endl;
150
12
    return help.str();
151
12
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/command_put.cpp
Line
Count
Source
1
#include "command_put.h"
2
#include "../../../src/CRON/cron.hpp"
3
4
command_put::command_put(const std::string &name):command(name)
5
8
{
6
8
}
7
8
std::string command_put::execute(std::vector<std::string> &v, thread_data *my_data)
9
1
{
10
1
    std::string str_buf = "command put - wrong paramiter: ";
11
1
    if (v.size() > 1){
12
1
        if (v[1] =="temperature")
13
1
        {
14
1
            str_buf.erase();
15
1
            my_data->main_iDomTools->send_temperature_thingSpeak();
16
1
            str_buf = "DONE";
17
1
        }
18
1
    }
19
1
    return str_buf;
20
1
}
21
22
std::string command_put::help()
23
1
{
24
1
    std::stringstream help;
25
1
    help << "put <parameter> - " << std::endl << std::endl;
26
1
    help << "parameter:" << std::endl;
27
1
    help << "\ttemperature - put actual temperature from inside and outside and smog on thingspeak\n" << std::endl;
28
1
    return help.str();
29
1
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_state_BT.cpp
Line
Count
Source
1
#include "../command_state.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_state_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_state_Class_fixture()
8
3
    {
9
3
10
3
    }
11
12
protected:
13
    std::unique_ptr<command_state> test_command_state;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
17
3
    {
18
3
        iDomTOOLS_ClassTest::SetUp();
19
3
        test_command_state = std::make_unique <command_state> ("state");
20
3
    }
21
22
    void TearDown() final
23
3
    {
24
3
        iDomTOOLS_ClassTest::TearDown();
25
3
    }
26
};
27
28
TEST_F(command_state_Class_fixture, stateAll)
29
1
{
30
1
    test_v.clear();
31
1
    test_v.push_back("state");
32
1
    test_v.push_back("all");
33
1
    auto ret = test_command_state->execute(test_v,&test_my_data);
34
1
    EXPECT_STREQ(ret.c_str(), "state: KODI=DEACTIVE alarm=DEACTIVE cameraLED=UNKNOWN house=UNDEFINE printer=OFF speakers=OFF ");
35
1
}
36
37
TEST_F(command_state_Class_fixture, stateGetOne)
38
1
{
39
1
    test_v.clear();
40
1
    test_v.push_back("state");
41
1
    test_v.push_back("KODI");
42
1
    auto ret = test_command_state->execute(test_v,&test_my_data);
43
1
    EXPECT_STREQ(ret.c_str(), "DEACTIVE");
44
1
}
45
46
TEST_F(command_state_Class_fixture, stateMissingParam)
47
1
{
48
1
    test_v.clear();
49
1
    test_v.push_back("state");
50
1
    auto ret = test_command_state->execute(test_v,&test_my_data);
51
1
    EXPECT_THAT(ret, testing::HasSubstr("need parameter!\n"));
52
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/command_show.cpp
Line
Count
Source
1
#include <strstream>
2
#include "command_show.h"
3
#include "../../../src/functions/functions.h"
4
5
command_show::command_show(const std::string &name):command(name)
6
16
{
7
16
8
16
}
9
10
std::string command_show::execute(std::vector<std::string> &v, thread_data *my_data)
11
9
{
12
9
    std::string str_buf = "show what?";
13
9
    if (v.size() > 1){
14
8
        if (v[1] =="log")
15
8
        {
16
4
            if (v.size() >2 && v.size() < 4){
17
1
                 return useful_F::l_send_file(_logfile,v[2],true);
18
1
            }
19
4
            else if (v.size() > 3){
20
2
                if (v[2] == "no"){
21
1
                 return useful_F::l_send_file(_logfile,v[3],false);
22
1
                }
23
2
                else{
24
1
                    return "do you mean : show log no <string>?";
25
1
                }
26
2
            }
27
4
            return useful_F::l_send_file(_logfile,"");
28
4
        }
29
8
        if (v[1]=="thread")
30
4
        {
31
3
            if (v.size() < 3){
32
1
                return "No ID";
33
1
            }
34
3
            else {
35
2
                if (v [2] !="all"){
36
1
                    std::stringstream ss;
37
1
                    ss << my_data->main_THREAD_arr->at(std::stoi(v[2])).thread_ID;
38
1
                    str_buf = my_data->main_THREAD_arr->at(std::stoi(v[2])).thread_name;
39
1
                    str_buf += "ID: ";
40
1
                    str_buf += ss.str();
41
1
                    str_buf += " socket: ";
42
1
                    str_buf += std::to_string(my_data->main_THREAD_arr->at(std::stoi(v[2])).thread_socket);
43
1
                    return str_buf;
44
1
                }
45
2
                else{
46
1
                    str_buf.erase();
47
1
                    std::stringstream ss;
48
11
                    for (int i =0; i< iDomConst::MAX_CONNECTION;++i)
49
10
                    {
50
10
                        ss.clear();
51
10
                        ss = std::stringstream();
52
10
                        str_buf += std::to_string(i)+" ";
53
10
                        str_buf += my_data->main_THREAD_arr->at(i).thread_name;
54
10
                        str_buf += "\t ID: ";
55
10
                        ss << my_data->main_THREAD_arr->at(i).thread_ID;
56
10
                        str_buf += ss.str();
57
10
                        int idSocket = my_data->main_THREAD_arr->at(i).thread_socket;
58
10
59
10
                        if (idSocket != 0 && idSocket != 1){
60
1
                            str_buf += " socket: ";
61
1
                            str_buf += std::to_string(my_data->main_THREAD_arr->at(i).thread_socket);
62
1
                        }
63
10
                        str_buf += "\n";
64
10
                    }
65
1
                    return str_buf;
66
1
                }
67
2
            }
68
3
        }
69
4
        else {
70
1
            return "wrong parameter: "+v[1];
71
1
        }
72
4
    }
73
9
    return str_buf;
74
9
}
75
76
std::string command_show::help()
77
1
{
78
1
    std::stringstream help;
79
1
    help << "show <parameter>- for show something" <<std::endl << std::endl;
80
1
    help << "parameter:" << std::endl;
81
1
    help << "\tlog             - show all server log" << std::endl;
82
1
    help << "\tlog <string>    - show all server log lines which contain <string>" << std::endl;
83
1
    help << "\tlog no <string> - show all server log lines which NO contain <string>" << std::endl;
84
1
    help << "\tthread all      - show all server thread pid " << std::endl;
85
1
    help << "\tthread <number> - show server <number> thread pid " << std::endl;
86
1
87
1
    return help.str();
88
1
}
89
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_test_BT.cpp
Line
Count
Source
1
#include "../commandtest.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_test_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_test_Class_fixture()
8
3
    {
9
3
10
3
    }
11
12
protected:
13
    std::unique_ptr<commandTEST> test_command_test;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
17
3
    {
18
3
        iDomTOOLS_ClassTest::SetUp();
19
3
        test_command_test = std::make_unique <commandTEST> ("test");
20
3
    }
21
22
    void TearDown() final
23
3
    {
24
3
        iDomTOOLS_ClassTest::TearDown();
25
3
    }
26
};
27
28
TEST_F(command_test_Class_fixture, test)
29
1
{
30
1
    test_v.push_back("test");
31
1
    test_v.push_back("test");
32
1
    auto ret = test_command_test->execute(test_v,&test_my_data);
33
1
    EXPECT_STREQ(ret.c_str(),"test - for test");
34
1
}
35
36
TEST_F(command_test_Class_fixture, throw)
37
1
{
38
1
    test_v.push_back("test");
39
1
    test_v.push_back("throw");
40
1
    EXPECT_THROW(test_command_test->execute(test_v,&test_my_data),std::string);
41
1
}
42
43
TEST_F(command_test_Class_fixture, unknownParam)
44
1
{
45
1
    test_v.push_back("test");
46
1
    test_v.push_back("fake");
47
1
    auto ret = test_command_test->execute(test_v,&test_my_data);
48
1
    EXPECT_EQ(ret.size(),49);
49
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/command_sleep.cpp
Line
Count
Source
1
#include "command_sleep.h"
2
#include "../../functions/functions.h"
3
#include "../../thread_functions/iDom_thread.h"
4
5
command_sleep::command_sleep(const std::string &name):command(name)
6
12
{
7
12
}
8
9
std::string command_sleep::execute(std::vector<std::string> &v, thread_data *my_data)
10
5
{   if (v.size()== 1)
11
5
    {
12
1
        return "sleep set to: "+ std::to_string(my_data->sleeper);
13
1
    }
14
5
    else if (v.size() == 3 ){
15
3
        if (v[1] == "set"){
16
2
            int sleep = 0;
17
2
            try {
18
2
                sleep = std::stoi(v[2]);
19
2
            }
20
2
            catch (...){
21
1
                return "system need intiger > 0 not: " +v[2];
22
1
            }
23
2
24
2
            my_data->sleeper = sleep;
25
1
26
1
            return iDOM_THREAD::start_thread("Sleep MPD",useful_F::sleeper_mpd,my_data);
27
2
        }
28
3
        else {
29
1
            return "wrong parametr "+v[1];
30
1
        }
31
3
    }
32
5
    return "internal error";
33
5
}
34
35
std::string command_sleep::help()
36
1
{
37
1
    std::stringstream help;
38
1
    help << "sleep - show actual time to stop play music" << std::endl;
39
1
    help << "sleep set <int> - start sleep for <int> minutes" << std::endl;
40
1
41
1
    return help.str();
42
1
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/TEST/command_uptime_BT.cpp
Line
Count
Source
1
#include "../command_uptime.h"
2
#include "../../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_uptime_Class_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_uptime_Class_fixture()
8
1
    {
9
1
10
1
    }
11
12
protected:
13
    std::unique_ptr<command_UPTIME> test_command_uptime;
14
15
    std::vector<std::string> test_v;
16
    void SetUp() final
17
1
    {
18
1
        iDomTOOLS_ClassTest::SetUp();
19
1
        test_command_uptime = std::make_unique <command_UPTIME> ("uptime");
20
1
    }
21
22
    void TearDown() final
23
1
    {
24
1
        iDomTOOLS_ClassTest::TearDown();
25
1
    }
26
};
27
28
TEST_F(command_uptime_Class_fixture, main)
29
1
{
30
1
    time(&test_my_data.start);
31
1
    test_v.push_back("uptime");
32
1
    auto ret = test_command_uptime->execute(test_v,&test_my_data);
33
1
    std::cout << "DATA: " << ret << std::endl;
34
1
    EXPECT_STREQ(ret.c_str(),"uptime: \n0 day 0 hours 0 minutes 0 seconds");
35
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/command_state.cpp
Line
Count
Source
1
#include "command_state.h"
2
3
command_state::command_state(const std::string &name):command(name)
4
10
{
5
10
}
6
7
std::string command_state::execute(std::vector<std::string> &v, thread_data *my_data)
8
3
{
9
3
    std::string ret = "need parameter!\n" + help();
10
3
    if (v.size() > 1)
11
3
    {
12
2
13
2
        if (v[1] == "all")
14
2
        {
15
1
            return my_data->main_iDomStatus->getAllObjectsStateString();
16
1
        }
17
2
        if (v[1] != "all")
18
1
        {
19
1
            return my_data->main_iDomStatus->getObjectStateString(v[1]);
20
1
        }
21
1
22
1
    }
23
3
    return ret;
24
3
}
25
26
std::string command_state::help()
27
4
{
28
4
    std::stringstream help;
29
4
    help << "state all/<name> - show state" << std::endl;
30
4
    return help.str();
31
4
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/command_433mhz.cpp
Line
Count
Source
1
#include "command_433mhz.h"
2
#include "../../RADIO_433_eq/radio_433_eq.h"
3
#include "../../433MHz/RFLink/rflinkhandler.h"
4
5
command_433MHz::command_433MHz(const std::string &name):command(name)
6
20
{
7
20
}
8
9
command_433MHz::~command_433MHz()
10
20
{
11
20
    // puts("command_433MHz::~command_433MHz()");
12
20
}
13
14
std::string command_433MHz::execute(std::vector<std::string> &v, thread_data *my_data)
15
40
{
16
40
    std::string str_buf = "wrong paramiter\n" + help();
17
40
    if (v.size() > 2){
18
40
        //////////////////////////// switch
19
40
        if (v[1] == "show" && v[2] == "all"){
20
21
            str_buf = my_data->main_REC->listAllName();
21
21
        }
22
19
        else if (v[1] == "delete" && v.size() == 3)
23
4
        {
24
4
            if (my_data->main_REC->nameExist(v[2]) == false)
25
1
            {
26
1
                return "equipment "+ v[2]+" not exist ";
27
1
            }
28
3
            my_data->main_REC->deleteRadioEq(v[2]);
29
3
            str_buf = v[2] + " deleted";
30
3
        }
31
15
        else if (v[1] == "add" && v.size() > 3) //zmień tu
32
7
        {
33
7
            RADIO_EQ_CONFIG cfg;
34
7
           /* if(v[2] == "SWITCH" && v.size() == 12)
35
7
                cfg.set(v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11]); // zmień tu
36
7
            else*/ if(v[2] == "BUTTON" && v.size() >= 6)
37
1
                cfg.set(v[2],v[3],v[4],v[5],v[6]); // zmień tu
38
6
            else if(v[2] == "WEATHER" && v.size() >= 4)
39
1
                cfg.set(v[2],v[3],v[4]); // zmień tu
40
5
            else
41
5
            {
42
5
                if (v.size() != 12)
43
1
                    return "mising paramiter!";
44
4
                cfg.set(v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11]); // zmień tu
45
4
                //return v[2] + " " + v[3] + " " + v[4] + "add more paramiter or wrong type";
46
4
}
47
7
            /////////////////////////////////////////////////////////////
48
7
            if (my_data->main_REC->nameExist(v[3]) == true)
49
1
            {
50
1
                return "equipment "+ v[3]+" exist ";
51
1
            }
52
5
            try
53
5
            {
54
5
                my_data->main_REC->addRadioEq(cfg,v[2]);
55
5
            }
56
5
            catch(const WRONG_FORMAT& )
57
5
            {
58
1
                return "wrong type "+v[2];
59
1
            }
60
1
            catch(const std::invalid_argument& )
61
1
            {
62
1
                return "wrong ID "+v[4];
63
1
            }
64
3
65
3
            str_buf = v[2] + " " + v[3] + " added";
66
3
            my_data->main_REC->saveConfig(my_data->server_settings->radio433MHzConfigFile);
67
3
        }
68
8
        else if (v[1] == "show" && v[2] == "switch"){
69
1
            str_buf = "";
70
1
            for (auto m_switch : my_data->main_REC->getSwitchPointerVector())
71
5
            {
72
5
                str_buf.append(stateToString(m_switch->getState()) );
73
5
            }
74
1
        }
75
7
        else if (v[1] == "show" && v[2] == "aether"){
76
1
            str_buf.clear();
77
1
            for(auto itr = my_data->main_RFLink->rflinkMAP.begin();
78
3
                itr != my_data->main_RFLink->rflinkMAP.end();
79
2
                itr++)
80
2
            {
81
2
                str_buf += itr->second.read();
82
2
                str_buf += '\n';
83
2
            }
84
1
            str_buf += ".";
85
1
86
1
        }
87
6
        else if (v[1] == "send"){
88
1
            str_buf = "sended!;";
89
1
            my_data->main_RFLink->sendCommand(v[2]);
90
1
91
1
        }
92
5
        else if (v[1] == "switch"){
93
5
            try{
94
5
                RADIO_SWITCH *m_switch = dynamic_cast<RADIO_SWITCH*>(my_data->main_REC->getEqPointer(v[2]));
95
5
96
5
                if (v[3] == "ON") {
97
1
                    m_switch->on();
98
1
                    str_buf = " done ";
99
1
                }
100
4
                else if (v[3] == "OFF"){
101
1
                    m_switch->off();
102
1
                    str_buf = " done ";
103
1
                }
104
3
                else if (v[3] == "15s"){
105
1
                    m_switch->onFor15sec();
106
1
                    str_buf = " done ";
107
1
                }
108
2
                else{
109
2
                    str_buf = "unknown paramiter: ";
110
2
                    str_buf.append(v[3]);
111
2
                }
112
5
            }
113
5
            catch (std::string& error){
114
1
                str_buf = error;
115
1
            }
116
5
            my_data->main_iDomTools->saveState_iDom();
117
5
        }
118
40
        /////////////////////////////////////////////
119
40
    }
120
40
    return str_buf;
121
40
}
122
123
std::string command_433MHz::help()
124
41
{
125
41
    std::stringstream help;
126
41
    help << ("433MHz delete <name> - dalete radio equipment") <<std::endl;
127
41
    help << ("433MHz add <type> <name> <ID> <onCode> <offCode> <on15sec> <sunrise> <sunset> <lock> <unlock> - add radio equipment") <<std::endl;
128
41
    help << ("433MHz switch <name> ON/OFF/15s - change switch state") <<std::endl;
129
41
    help << ("433MHz show all - list all equipment by name") <<std::endl;
130
41
    help << ("433MHz show aether - show aether devices by ID") <<std::endl;
131
41
    help << ("433MHz send <msg> - send command") <<std::endl;
132
41
    return help.str();
133
41
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/command_uptime.cpp
Line
Count
Source
1
#include "command_uptime.h"
2
#include "../../../src/functions/functions.h"
3
4
command_UPTIME::command_UPTIME(const std::string &name):command(name)
5
8
{
6
8
7
8
}
8
9
std::string command_UPTIME::execute(std::vector<std::string> &v, thread_data *my_data)
10
1
{
11
1
    std::string str_buf;
12
1
    time(&my_data->now_time);
13
1
    str_buf ="uptime: ";
14
1
    str_buf.append(useful_F::sek_to_uptime(difftime(my_data->now_time,my_data->start) ) );
15
1
    return str_buf;
16
1
}
17
18
std::string command_UPTIME::help()
19
1
{
20
1
    std::stringstream help;
21
1
    help << "uptime - show server uptime" << std::endl;
22
1
    return help.str();
23
1
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/command_ardu.cpp
Line
Count
Source
1
#include "command_ardu.h"
2
3
command_ardu::command_ardu(const std::string &name):command(name)
4
1
{
5
1
    this->m_mainRadioButton = std::nullptr_t();
6
1
}
7
8
command_ardu::command_ardu(const std::string& name, thread_data *my_data):command(name)
9
  ,m_button433MHzVector(my_data->main_REC->getButtonPointerVector())
10
18
{
11
18
    //m_button433MHzVector = my_data->main_REC->getButtonPointerVector();
12
18
    m_mainRadioButton = static_cast<RADIO_BUTTON*>(my_data->main_REC->getEqPointer("locker"));
13
18
14
18
    m_weatherStVe = my_data->main_REC->getWeather_StationPtrVector();
15
18
    m_mainWeatherStation = static_cast<RADIO_WEATHER_STATION*>(my_data->main_REC->getEqPointer("first"));
16
18
}
17
18
std::string command_ardu::execute(std::vector<std::string> &v, thread_data *my_data)
19
14
{
20
14
    std::string str_buf = " only for internal usage!";
21
14
    if (v.size() > 1){
22
14
        if(v[1] == "show"){
23
1
            RADIO_WEATHER_STATION* st = static_cast<RADIO_WEATHER_STATION*>(my_data->main_REC->getEqPointer("first"));
24
1
            str_buf = st->data.getDataString();
25
1
        }
26
14
        if(v[1] == "433MHz"){
27
13
            my_data->myEventHandler.run("433MHz")->addEvent("RFLink: "+v[2]);
28
13
            try {
29
13
                my_data->main_RFLink->
30
13
                        rflinkMAP[my_data->main_RFLink->getArgumentValueFromRFLinkMSG(v[2],
31
13
                        "ID")].counter();
32
13
                my_data->main_RFLink->
33
13
                        rflinkMAP[my_data->main_RFLink->getArgumentValueFromRFLinkMSG(v[2],
34
13
                        "ID")].msg = v[2];
35
13
            }
36
13
            catch(const std::string& e){
37
3
                std::cout << "wyjatek w szukaniu: " << e <<std::endl;
38
3
                pingAndOkRecv( my_data, v[2]);
39
3
            }
40
13
            //TODO add command
41
13
            try {
42
12
                if (m_mainRadioButton->getID() == my_data->main_RFLink->getArgumentValueFromRFLinkMSG(v[2],"ID") )
43
6
                {
44
6
                    my_data->main_iDomTools->button433mhzLockerPressed(m_mainRadioButton);
45
6
                }
46
12
            }
47
12
            catch (const std::string& e){ }
48
12
            try {
49
12
                if (m_mainWeatherStation->getID() == my_data->main_RFLink->getArgumentValueFromRFLinkMSG(v[2],"ID") )
50
3
                {
51
3
                    m_mainWeatherStation->data.putData(v[2]);
52
3
                }
53
12
            }
54
12
            catch (std::string& e){ }
55
12
        }
56
14
    }
57
14
    return str_buf;
58
14
}
59
60
std::string command_ardu::help()
61
2
{
62
2
    return " only for internal usege\n";
63
2
}
64
65
void command_ardu::pingAndOkRecv(thread_data *my_data, const std::string& s)
66
3
{
67
3
    if (s.find("OK;") != std::string::npos)
68
1
        my_data->main_RFLink->okTime = Clock::getUnixTime();
69
2
    else if (s.find("PONG;") != std::string::npos)
70
1
        my_data->main_RFLink->pingTime = Clock::getUnixTime();
71
3
    std::cout << "poing && ok recv " << s <<std::endl
72
3
              << " ok time: "<<my_data->main_RFLink->okTime<< std::endl
73
3
              << " ping time: "<<my_data->main_RFLink->pingTime<< std::endl;
74
3
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/commandexit.cpp
Line
Count
Source
1
#include "commandexit.h"
2
3
commandEXIT::commandEXIT(const std::string &name):command(name)
4
8
{
5
8
}
6
7
std::string commandEXIT::execute(std::vector<std::string> &v, thread_data *my_data)
8
1
{
9
1
    return "\nEND.\n";
10
1
}
11
12
std::string commandEXIT::help()
13
1
{
14
1
    return "exit - disconnect from server\n";
15
1
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/command_big.cpp
Line
Count
Source
1
#include "command_big.h"
2
3
command_big::command_big(const std::string &name):command(name)
4
8
{
5
8
6
8
}
7
8
std::string command_big::execute(std::vector<std::string> &v, thread_data *my_data)
9
1
{
10
1
    std::string str_buf = "command big - wrong paramiter:\n "+ help();
11
1
    if (v.size() > 1){
12
1
        str_buf.erase();
13
55
        for (int i =0; i < std::stoi(v[1])-1; ++i){
14
54
            str_buf += "z";
15
54
        }
16
1
        str_buf += "Y";
17
1
    }
18
1
    return str_buf;
19
1
}
20
21
std::string command_big::help()
22
2
{
23
2
    return "big <number> - send big (number) data \n";
24
2
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/commandrs232.cpp
Line
Count
Source
1
#include "commandrs232.h"
2
#include "../../../src/functions/functions.h"
3
4
commandRS232::commandRS232(const std::string &name):command(name)
5
15
{
6
15
}
7
std::string commandRS232::execute(std::vector<std::string> &v, thread_data *my_data)
8
8
{
9
8
    std::string str_buf ="default";
10
8
11
8
    if (v[1]=="get")
12
8
    {
13
2
        if (v[2]=="temperature")
14
2
        {
15
1
            str_buf = useful_F::send_to_arduino(my_data,"temperature:339;");
16
1
            str_buf += std::to_string(++counter);
17
1
        }
18
2
        else
19
2
        {
20
1
            str_buf = ("wrong parameter: "+v[2]);
21
1
        }
22
2
    }
23
8
24
8
    else if (v[1]=="send")
25
6
    {
26
1
        str_buf = useful_F::send_to_arduino(my_data,v[2]);
27
1
    }
28
6
    else if (v[1]=="error")
29
5
    {
30
4
        if (v.size() < 3 )
31
4
            return "add more parameter to error";
32
4
        std::string msg;
33
10
        for (unsigned int i = 2; i < v.size(); ++i)
34
7
        {
35
7
            msg+=" ";
36
7
            msg+=v[i];
37
7
        }
38
3
        if(v[2]=="Temperature" && v[3]=="error")
39
3
        {
40
1
41
1
            my_data->myEventHandler.run("RS232")->addEvent("RS232 error event: "+msg);
42
1
            log_file_mutex.mutex_lock();
43
1
            log_file_cout << WARNING<< "RS232 ERROR event: " << msg << std::endl;
44
1
            log_file_mutex.mutex_unlock();
45
1
        }
46
3
        else if (v[2]=="test" && v[3]=="msg")
47
2
        {
48
1
            log_file_mutex.mutex_lock();
49
1
            log_file_cout << DEBUG << "RS232 ERROR debug : "<<msg << std::endl;
50
1
            log_file_mutex.mutex_unlock();
51
1
            str_buf = "DONE!";
52
1
        }
53
2
        else
54
2
        {
55
1
            log_file_mutex.mutex_lock();
56
1
            log_file_cout << CRITICAL << "RS232 ERROR unknown : "<<msg << std::endl;
57
1
            log_file_mutex.mutex_unlock();
58
1
        }
59
3
    }
60
5
    else
61
5
    {
62
1
        str_buf = ("wrong parameter: "+v[1]);
63
1
    }
64
8
    return str_buf;
65
8
}
66
67
std::string commandRS232::help()
68
1
{
69
1
    std::stringstream help;
70
1
    help << "RS232 - communication with Arduino:" << std::endl;
71
1
    help << "parameter:" << std::endl << std::endl;
72
1
    help << "\tsend <command> - send <command> to Arduino" << std::endl;
73
1
    help << "\tget <param> - get <param> from Arduino" << std::endl;
74
1
    help << "\t\ttemperature - get temeprature INSIDE + OUTSIDE" << std::endl;
75
1
76
1
    return help.str();
77
1
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/command_clock.cpp
Line
Count
Source
1
#include "command_clock.h"
2
#include "../../../src/functions/functions.h"
3
4
command_clock::command_clock(const std::string &name):command(name)
5
9
{
6
9
7
9
}
8
9
std::string command_clock::execute(std::vector<std::string> &v, thread_data *my_data)
10
2
{
11
2
    if (v.size() > 1){
12
1
        return "clock set "+ useful_F::send_to_arduino_clock(my_data,v[1]);
13
1
    }
14
1
    return "can not set clock";
15
1
}
16
17
std::string command_clock::help()
18
1
{
19
1
    return "clock <number/string> - put number/string (max 4 digits) to 7segment LCD\n";
20
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/commandtest.cpp
Line
Count
Source
1
#include "commandtest.h"
2
#include "../../functions/functions.h"
3
#include "../../../ftplibpp/ftplib.h"
4
5
commandTEST::commandTEST(const std::string &name):command(name)
6
10
{
7
10
}
8
9
std::string commandTEST::execute(std::vector<std::string> &v, thread_data *my_data)
10
3
{
11
3
12
3
    if (v[1] == "test")
13
3
    {
14
1
        std::string msg = "test - for test";
15
1
        my_data->main_iDomTools->runOnSunrise();
16
1
        return msg;
17
1
    }
18
3
    else if (v[1] == "throw")
19
2
    {
20
1
        throw std::string("test throw");
21
1
    }
22
3
    return help();
23
3
}
24
std::string commandTEST::help()
25
2
{
26
2
    std::stringstream help;
27
2
    help << "test - for test" << std::endl;
28
2
    help << "throw - trow test reload program" << std::endl;
29
2
    return help.str();
30
2
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/command_cmd.cpp
Line
Count
Source
1
#include "command_cmd.h"
2
#include "../../../src/functions/functions.h"
3
4
command_cmd::command_cmd(const std::string &name):command(name)
5
9
{
6
9
7
9
}
8
9
std::string command_cmd::execute(std::vector<std::string> &v, thread_data *my_data)
10
2
{
11
2
    if (v.size() == 1){
12
1
        return "fifo file contain: "+ useful_F_libs::read_from_mkfifo(my_data->server_settings->omxplayerFile);
13
1
    }
14
1
    return "error: unknown parameter: "+v[1];
15
1
}
16
17
std::string command_cmd::help()
18
1
{
19
1
    return "cmd - read char prom cmd fifo file for unblock video player\n";
20
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandhandler.cpp
Line
Count
Source
1
#include <iostream>
2
#include "../../libs/emoji/emoji.h"
3
#include "commandhandler.h"
4
#include "commandClass/command_mpd.h"
5
#include "commandClass/commandrs232.h"
6
#include "commandClass/command_uptime.h"
7
#include "commandClass/command_big.h"
8
#include "commandClass/command_clock.h"
9
#include "commandClass/command_hello.h"
10
#include "commandClass/command_help.h"
11
#include "commandClass/command_ip.h"
12
#include "commandClass/command_put.h"
13
#include "commandClass/command_sleep.h"
14
#include "commandClass/command_ok.h"
15
#include "commandClass/command_show.h"
16
#include "commandClass/command_idom.h"
17
#include "commandClass/command_program.h"
18
#include "commandClass/commandexit.h"
19
#include "commandClass/commandtest.h"
20
#include "commandClass/command_log.h"
21
#include "commandClass/command_state.h"
22
#include "commandClass/command_ardu.h"
23
24
commandHandler::commandHandler(thread_data * my_data)
25
7
{
26
7
    std::unique_ptr <command> test(new commandTEST("test") );
27
7
    commandMap.insert( std::make_pair(test->getCommandName(),std::move( test )) );
28
7
29
7
    std::unique_ptr <command> program(new command_program("program") );
30
7
    commandMap.insert( std::make_pair(program->getCommandName(),std::move( program )) );
31
7
32
7
    std::unique_ptr <command> eexit(new commandEXIT("exit"));
33
7
    commandMap.insert( std::make_pair(eexit->getCommandName(),std::move( eexit )) );
34
7
35
7
    std::unique_ptr <command> MPD(new command_mpd("MPD"));
36
7
    commandMap.insert(std::make_pair(MPD->getCommandName(), std::move (MPD)));
37
7
38
7
    std::unique_ptr <command> RS232 (new commandRS232("RS232"));
39
7
    commandMap.insert(std::make_pair(RS232->getCommandName(), std::move(RS232)));
40
7
41
7
    std::unique_ptr <command> uptime (new command_UPTIME("uptime"));
42
7
    commandMap.insert(std::make_pair(uptime->getCommandName(), std::move(uptime)));
43
7
44
7
    std::unique_ptr <command> big (new command_big("big"));
45
7
    commandMap.insert(std::make_pair(big->getCommandName(), std::move(big)));
46
7
47
7
    std::unique_ptr <command> clock (new command_clock("clock"));
48
7
    commandMap.insert(std::make_pair(clock->getCommandName(), std::move(clock)));
49
7
50
7
    std::unique_ptr <command> hello (new command_hello("hello"));
51
7
    commandMap.insert(std::make_pair(hello->getCommandName(), std::move(hello)));
52
7
53
7
    std::unique_ptr <command> help (new command_help("help"));
54
7
    commandMap.insert(std::make_pair(help->getCommandName(), std::move(help)));
55
7
56
7
    std::unique_ptr <command> ip (new command_ip("ip"));
57
7
    commandMap.insert(std::make_pair(ip->getCommandName(), std::move(ip)));
58
7
59
7
    std::unique_ptr <command> ok (new command_ok("ok"));
60
7
    commandMap.insert(std::make_pair(ok->getCommandName(), std::move(ok)));
61
7
62
7
    std::unique_ptr <command> show (new command_show("show"));
63
7
    commandMap.insert(std::make_pair(show->getCommandName(), std::move(show)));
64
7
65
7
    std::unique_ptr <command> sleep (new command_sleep("sleep"));
66
7
    commandMap.insert(std::make_pair(sleep->getCommandName(), std::move(sleep)));
67
7
68
7
    std::unique_ptr <command> put (new command_put("put"));
69
7
    commandMap.insert(std::make_pair(put->getCommandName(), std::move(put)));
70
7
71
7
    std::unique_ptr <command> iDom (new command_iDom("iDom"));
72
7
    commandMap.insert(std::make_pair(iDom->getCommandName(), std::move(iDom)));
73
7
74
7
    std::unique_ptr <command> log (new command_log("log"));
75
7
    commandMap.insert(std::make_pair(log->getCommandName(), std::move(log)));
76
7
77
7
    std::unique_ptr <command> state (new command_state("state"));
78
7
    commandMap.insert(std::make_pair(state->getCommandName(), std::move(state)));
79
7
80
7
    std::unique_ptr <command> ardu (new command_ardu("ardu", my_data));
81
7
    commandMap.insert(std::make_pair(ardu->getCommandName(), std::move(ardu)));
82
7
83
7
    this->my_data = my_data;
84
7
    this->my_data->commandMapPtr = &commandMap;
85
7
}
86
87
commandHandler::~commandHandler()
88
7
{
89
7
    puts("commandHandler::~commandHandler()");
90
7
}
91
92
std::string commandHandler::run(std::vector<std::string> &v, thread_data *my_data)
93
3
{
94
3
    if (commandMap.find(v[0]) == commandMap.end()){
95
1
        std::fstream log;
96
1
        log.open( "/mnt/ramdisk/command.txt", std::ios::binary | std::ios::in | std::ios::out|std::ios::app );
97
1
        log << v[0] << std::endl;
98
1
        log.close();
99
1
        return EMOJI::emoji(E_emoji::WARNING_SIGN)+" unknown command: "+ v[0];
100
1
    }
101
3
    else{
102
2
        return commandMap[v[0]]->execute(v,my_data);
103
2
    }
104
3
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/command_event.cpp
Line
Count
Source
1
#include "command_event.h"
2
3
command_event::command_event(const std::string &name) :command(name)
4
13
{
5
13
6
13
}
7
8
std::string command_event::execute(std::vector<std::string> &v, thread_data *my_data)
9
6
{
10
6
    if (v.size() == 1){
11
1
        return my_data->myEventHandler.getListPossibleEvents();
12
1
    }
13
5
    if (v.size() == 2){
14
1
        return my_data->myEventHandler.run(v[1])->getEvent();
15
1
    }
16
4
    if (v.size() == 3 && v[2]=="clear"){
17
1
        my_data->myEventHandler.run(v[1])->clearEvent();
18
1
        return "event " +v[1]+ " has been cleared!";
19
1
    }
20
3
    if (v.size() == 3 && v[2]=="intensity"){
21
1
        std::stringstream intensity;
22
1
        intensity << my_data->myEventHandler.run(v[1])->getLast1minNumberEvent();
23
1
        return "event " +v[1]+" "+ intensity.str() +" intensity per last minute!";
24
1
    }
25
2
    if (v.size() == 5 && v[2]=="clear"){
26
1
        unsigned int from = std::stoi(v[3]);
27
1
        unsigned int to = std::stoi(v[4]);
28
1
        my_data->myEventHandler.run(v[1])->clearEvent(from, to);
29
1
        return "event " +v[1]+ " has been cleared!";
30
1
    }
31
1
    return my_data->myEventHandler.help();
32
1
}
33
34
std::string command_event::help()
35
1
{
36
1
    std::stringstream help;
37
1
    help << "event- show actual event (all)" << std::endl;
38
1
    help << "event <name> - show one event" << std::endl;
39
1
    help << "event <name> clear - clear event <name>" << std::endl;
40
1
    help << "event <name> intensity - intensity per minute" <<std::endl;
41
1
    return help.str();
42
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandhandlerroot.cpp
Line
Count
Source
1
#include "commandhandlerroot.h"
2
#include "commandClass/command_cmd.h"
3
#include "commandClass/command_event.h"
4
#include "commandClass/command_433mhz.h"
5
6
commandHandlerRoot::commandHandlerRoot(thread_data * my_data): commandHandler(my_data)
7
7
{
8
7
    std::unique_ptr <command> cmd (new command_cmd("cmd"));
9
7
    commandMap.insert(std::make_pair(cmd->getCommandName(), std::move(cmd)));
10
7
11
7
    std::unique_ptr <command> event (new command_event("event"));
12
7
    commandMap.insert(std::make_pair(event->getCommandName(), std::move(event)));
13
7
14
7
    std::unique_ptr <command> r_433MHz (new command_433MHz("433MHz"));
15
7
    commandMap.insert(std::make_pair(r_433MHz->getCommandName(), std::move(r_433MHz)));
16
7
}
17
18
commandHandlerRoot::~commandHandlerRoot()
19
7
{
20
7
    puts("commandHandlerRoot::~commandHandlerRoot()");
21
7
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/command_hello.cpp
Line
Count
Source
1
#include "command_hello.h"
2
3
command_hello::command_hello(const std::string &name):command(name)
4
8
{
5
8
}
6
7
command_hello::~command_hello()
8
8
{
9
8
}
10
11
std::string command_hello::execute(std::vector<std::string> &v, thread_data *my_data)
12
1
{
13
1
    return "\nHI You User!\n";
14
1
}
15
16
std::string command_hello::help()
17
1
{
18
1
    return "hello - send test message to server if connection is ok, the server response: \"HI!\"\n";
19
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandhandlerrs232.cpp
Line
Count
Source
1
#include "commandhandlerrs232.h"
2
#include "commandClass/command_cmd.h"
3
#include "commandClass/command_event.h"
4
5
6
commandHandlerRS232::commandHandlerRS232(thread_data *my_data):commandHandlerRoot(my_data)
7
1
{
8
1
9
1
}
10
11
commandHandlerRS232::~commandHandlerRS232()
12
1
{
13
1
    puts("commandHandlerRS232::~commandHandlerRS232()");
14
1
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/command_help.cpp
Line
Count
Source
1
#include "command_help.h"
2
#include <vector>
3
#include <algorithm>
4
5
command_help::command_help(const std::string &name):command(name)
6
10
{
7
10
}
8
9
std::string command_help::execute(std::vector<std::string> &v, thread_data *my_data)
10
3
{
11
3
    std::string result ="";
12
3
    if (v.size() ==2){
13
2
14
2
        if (my_data->commandMapPtr->find(v[1]) == my_data->commandMapPtr->end()){
15
1
            return "unknown command: "+ v[1]+" help note not found";
16
1
        }
17
1
        else{
18
1
            return my_data->commandMapPtr->find(v[1])->second->help();
19
1
        }
20
1
    }
21
1
    else
22
1
    {
23
23
        for( auto iter= my_data->commandMapPtr->begin();iter != my_data->commandMapPtr->end(); ++iter ) {
24
22
25
22
            result+= iter->second->help();
26
22
            result+= "------------------------------------\n";
27
22
        }
28
1
    }
29
3
    return result;
30
3
}
31
32
std::string command_help::help()
33
1
{
34
1
    return "help - show help for all command \nhelp <parameter> - show help for command\n";
35
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/test/commandhandler_BT.cpp
Line
Count
Source
1
#include "../commandhandlerrs232.h"
2
#include "../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_handler_rs232_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_handler_rs232_fixture()
8
1
    {
9
1
10
1
    }
11
12
protected:
13
    std::unique_ptr<commandHandlerRS232> test_chRS232;
14
    std::vector<std::string> test_v;
15
    void SetUp() final
16
1
    {
17
1
        iDomTOOLS_ClassTest::SetUp();
18
1
        test_chRS232 = std::make_unique<commandHandlerRS232>(&test_my_data);
19
1
    }
20
21
    void TearDown() final
22
1
    {
23
1
        iDomTOOLS_ClassTest::TearDown();
24
1
    }
25
};
26
27
TEST_F(command_handler_rs232_fixture, main)
28
1
{
29
1
    test_v.push_back("ok");
30
1
    auto ret = test_chRS232->run(test_v, &test_my_data);
31
    EXPECT_STREQ(ret.c_str(), "\nEND\n");
32
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/command_idom.cpp
Line
Count
Source (jump to first uncovered line)
1
#include "command_idom.h"
2
#include "../../functions/functions.h"
3
4
command_iDom::command_iDom(const std::string &name):command(name)
5
27
{
6
27
}
7
8
std::string command_iDom::execute(std::vector<std::string> &v, thread_data *my_data)
9
30
{
10
30
    if (v.size()<2){
11
1
        return "need parameter!\n" + help();
12
1
    }
13
29
    if (v[1]=="speakers")
14
3
    {
15
3
        if (v[2] =="ON"){
16
1
            iDomTOOLS::turnOnSpeakers();
17
1
            return "speakers ON";
18
1
        }
19
2
        else if (v[2]=="OFF"){
20
1
            iDomTOOLS::turnOffSpeakers();
21
1
            return "speakers OFF";
22
1
        }
23
1
        else{
24
1
            return "unknow speakers action: "+v[2];
25
1
        }
26
26
    }
27
26
    else if (v[1]=="sunset"){
28
1
        return my_data->main_iDomTools->getSunset(true);
29
1
    }
30
25
    else if (v[1]=="sunrise"){
31
1
        return my_data->main_iDomTools->getSunrise(true);
32
1
    }
33
24
    else if (v[1]=="day" && v[2]=="lenght"){
34
1
        return my_data->main_iDomTools->getDayLenght(true);
35
1
    }
36
23
    else if (v[1]=="sun"){
37
1
        std::string ret;
38
1
        ret = my_data->main_iDomTools->getSunrise(true);
39
1
        ret.append("\n");
40
1
        ret.append(my_data->main_iDomTools->getSunset(true));
41
1
        ret.append("\n");
42
1
        ret.append(my_data->main_iDomTools->getDayLenght(true));
43
1
        ret.append("\n");
44
1
        return ret;
45
1
    }
46
22
    else if (v[1]=="sysinfo"){
47
1
        return my_data->main_iDomTools->getSystemInfo();
48
1
    }
49
21
    else if (v[1]=="temperature"){
50
2
        if ( v.size() < 3){
51
1
            return my_data->main_iDomTools->getTemperatureString();
52
1
        }
53
1
        else {
54
1
            if (v[2] == "stats"){
55
1
                std::string ret;
56
1
                try{
57
1
                 ret = my_data->main_iDomTools->getThermoStats(v[3]);
58
1
                }
59
1
                catch (std::string& obj){
60
1
                    ret = obj +" "+v[3];
61
1
                }
62
1
               return ret;
63
19
            }
64
1
        }
65
19
    }
66
19
    else if (v[1]=="text"){
67
1
        return my_data->main_iDomTools->getTextToSpeach();
68
1
    }
69
18
    else if (v[1] == "lock"){
70
1
        my_data->main_iDomTools->lockHome();
71
1
        return "hous locked";
72
1
    }
73
17
    else if (v[1] == "unlock"){
74
1
        my_data->main_iDomTools->unlockHome();
75
1
        return "hous unlocked";
76
1
    }
77
16
    else if (v[1]=="LED"){
78
2
        if (v.size() != 7){
79
2
            if (v[2]=="OFF"){
80
1
                return my_data->main_iDomTools->ledOFF();
81
1
            }
82
1
            else if(v[2] == "set"){
83
0
               return my_data->main_iDomTools->ledOn(
84
0
                            my_data->ptr_pilot_led->colorLED[2],
85
0
                            std::stoi(v[3]),
86
0
                            std::stoi(v[4])
87
0
                            );
88
0
            }
89
1
            else{
90
1
                return "need more parameter from-to-R-G-B";
91
1
            }
92
0
        }
93
0
        else {
94
0
            LED_Strip strip(v[2],v[3],v[4],v[5],v[6]);
95
0
            return my_data->main_iDomTools->ledOn(strip);
96
0
        }
97
14
    }
98
14
    else if (v[1]=="say"){
99
1
        if (v.size() > 3){
100
1
            std::vector<std::string> vTTS ={ my_data->main_iDomTools->getTextToSpeach()};
101
1
            my_data->main_iDomTools->textToSpeach(&vTTS);
102
1
            return "sad";
103
1
        }
104
13
    }
105
13
    else if (v[1]=="smog"){
106
1
        return my_data->main_iDomTools->getSmog()+" mg/m^3";
107
1
    }
108
12
    else if (v[1]=="230V"){
109
3
        if (v.size() > 2 && v[2]=="ON"){
110
1
            my_data->main_iDomTools->turnOnPrinter();
111
1
            return "230V ON";
112
1
        }
113
2
        else if(v.size() > 2 && v[2]=="OFF"){
114
1
            my_data->main_iDomTools->turnOffPrinter();
115
1
            return "230V OFF";
116
1
        }
117
1
        else {
118
1
            return "wrong paramiter";
119
1
        }
120
9
    }
121
9
    else if (v[1]=="wifi"){
122
1
        std::string readBuffer = useful_F_libs::httpPost("http://cyniu88.no-ip.pl/cgi-bin/kto_wifi.sh",10);
123
1
        return readBuffer;
124
1
    }
125
8
    else if (v[1]=="lightning"){
126
1
        std::stringstream readBuffer;
127
1
        readBuffer << my_data->main_iDomTools->getLightningStruct().data.str();
128
1
        readBuffer << std::endl;
129
1
        readBuffer << "bool: " << my_data->main_iDomTools->getLightningStruct().riseAlarm;
130
1
        readBuffer <<std::endl <<" time: ";
131
1
        readBuffer << Clock::getTime().getString();
132
1
        return readBuffer.str();
133
1
    }
134
7
    else if (v[1]=="kill"){
135
0
136
0
        if (v[2]=="thread"){
137
0
            my_data->main_THREAD_arr->at(std::stoi(v[3]) ).thread.~thread();
138
0
            return "done!";
139
0
        }
140
7
    }
141
7
    else if (v[1]=="facebook"){
142
0
        std::string msg;
143
0
        for (unsigned int i = 2; i < v.size(); ++i){
144
0
            msg+=" ";
145
0
            msg+=v[i];
146
0
        }
147
0
        return my_data->main_iDomTools->postOnFacebook(msg);
148
0
    }
149
7
    else if (v[1]=="viber"){
150
0
        std::string msg;
151
0
        for (unsigned int i = 2; i < v.size(); ++i){
152
0
            msg+=" ";
153
0
            msg+=v[i];
154
0
        }
155
0
        STATE stMSG = my_data->main_iDomTools->sendViberMsgBool(msg, my_data->server_settings->viberReceiver.at(0),
156
0
                                                     my_data->server_settings->viberSender);
157
0
        if(stMSG == STATE::SEND_OK){
158
0
            return "wiadomosc wyslana poprawnie";
159
0
        }
160
0
        else{
161
0
            return "blad wysylania wiadomosci - sprawdz logi";
162
0
        }
163
7
    }
164
7
    else if (v[1] == "camera"){
165
3
166
3
        if (v.size() < 4){
167
1
            return "not enough parameters";
168
1
        }
169
2
        if (v[2]=="LED" && v[3] == "ON"){
170
1
            my_data->main_iDomTools->cameraLedON(my_data->server_settings->cameraLedON);
171
1
        }
172
1
        else if (v[2]=="LED" && v[3] == "OFF"){
173
1
            my_data->main_iDomTools->cameraLedOFF(my_data->server_settings->cameraLedOFF);
174
1
        }
175
2
        return "led DONE";
176
2
    }
177
4
    else if (v[1]=="weather"){
178
0
179
0
        if (v.size() < 4){
180
0
            return "not enough parameters";
181
0
        }
182
0
        std::string tempHTML = my_data->main_iDomTools->getWeatherEvent(v[2],std::stoi(v[3]));
183
0
        return useful_F_libs::removeHtmlTag(tempHTML);
184
0
    }
185
4
    else if (v[1] == "KODI"){
186
3
        return my_data->main_iDomTools->startKodi_Thread();
187
3
    }
188
1
    else if (v[1]=="alarm"){
189
0
190
0
        if (v.size() < 3){
191
0
            return "not enough parameters";
192
0
        }
193
0
        if (v[2] == "OFF"){
194
0
            my_data->alarmTime.state = STATE::DEACTIVE;
195
0
            my_data->main_iDomStatus->setObjectState("alarm", my_data->alarmTime.state);
196
0
            my_data->main_iDomTools->saveState_iDom();
197
0
            return "alarm clock has been deactivated";
198
0
        }
199
0
        else if (v[2] == "GET"){
200
0
            return my_data->alarmTime.time.getString();
201
0
        }
202
0
        else if (v[2] == "SET" && v.size() == 5){
203
0
            if (v[3] == "from")
204
0
            {
205
0
                my_data->alarmTime.fromVolume = std::stoi(v[4]);
206
0
            }
207
0
            else if (v[3] == "to")
208
0
            {
209
0
                my_data->alarmTime.toVolume = std::stoi(v[4]);
210
0
            }
211
0
            else if (v[3] == "radio")
212
0
            {
213
0
                my_data->alarmTime.radioID = std::stoi(v[4]);
214
0
            }
215
0
            std::stringstream ret;
216
0
            ret << "The values has beedn set:" << std::endl;
217
0
            ret << "From Value: " << my_data->alarmTime.fromVolume << std::endl;
218
0
            ret << "To Value: " << my_data->alarmTime.toVolume << std::endl;
219
0
            ret << "Radio ID: " << my_data->alarmTime.radioID << std::endl;
220
0
            my_data->main_iDomTools->saveState_iDom();
221
0
            return ret.str();
222
0
        }
223
0
        else if (v[2] == "ON" && v.size() > 3){
224
0
            my_data->alarmTime.time = Clock(v[3]);
225
0
            my_data->alarmTime.state = STATE::ACTIVE;
226
0
            my_data->main_iDomStatus->setObjectState("alarm", my_data->alarmTime.state);
227
0
            my_data->main_iDomTools->saveState_iDom();
228
0
            return "alarm clock has been activated";
229
0
        }
230
1
    }
231
1
    return "iDom - unknown parameter: "+ v[1];
232
1
}
233
234
std::string command_iDom::help()
235
3
{
236
3
    std::stringstream help;
237
3
    help << "iDom - for control smart home" << std::endl;
238
3
    help << "iDom speakers ON/OFF - to on or off speakers" << std::endl;
239
3
    help << "iDom 230v ON/OFF     - to on or off printers" << std::endl;
240
3
    help << "iDom sunset/sunrise/day lenght - to show those parameters" << std::endl;
241
3
    help << "iDom sun        - get sunrise, sunset and day lenght" << std::endl;
242
3
    help << "iDom sysinfo    - get system info" << std::endl;
243
3
    help << "iDom text       - get text to speach" << std::endl;
244
3
    help << "iDom say <text> - say standatrd info or <text>" << std::endl;
245
3
    help << "iDom sms <text> - send sms<text>" << std::endl;
246
3
    help << "iDom LED <FROM> <TO> <R> <G> <B> - set RGB LED strip" << std::endl;
247
3
    help << "iDom LED OFF    - led off" << std::endl;
248
3
    help << "iDom LED set <from> <to> - set green led from to" << std::endl;
249
3
    help << "iDom temperature - get temperature from all termomether" << std::endl;
250
3
    help << "iDom temperature stats <name> - get temperature stats from termomether <name>" << std::endl;
251
3
    help << "iDom smog       - get current SMOG level (KRAKOW)" << std::endl;
252
3
    help << "iDom kill thread <ID>  - kill thread but denger!" << std::endl;
253
3
    help << "iDom camera LED ON/OFF - LED camera work" << std::endl;
254
3
    help << "iDom facebook ... - post on facebook wall" << std::endl;
255
3
    help << "iDom viber ...   - send viber msg" << std::endl;
256
3
    help << "iDom weather <city> <radius> - get weather alert" << std::endl;
257
3
    help << "iDom lightning  - get lightning alert" << std::endl;
258
3
    help << "iDom alarm ON/OFF hh:mm - set larm clock" << std::endl;
259
3
    help << "iDom alarm SET from/to/radio <value> - set larm clock" << std::endl;
260
3
    help << "iDom alarm GET - get alarm time" << std::endl;
261
3
    help << "iDom lock   - lock home" << std::endl;
262
3
    help << "iDom unlock - unlock home" << std::endl;
263
3
    help << "iDom KODI - start KODI smart TV" << std::endl;
264
3
    help << "iDom wifi - show all wifi client" << std::endl;
265
3
    return help.str();
266
3
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/test/commandhandler_stub.cpp
Line
Count
Source
1
#include "../../src/functions/functions.h"
2
#include "../../src/LCD_c/lcd_c.h"
3
4
//std::string useful_F::send_to_arduino (thread_data *my_data_logic, const std::string& msg){
5
//    return "retunr test ";
6
//}
7
8
5
std::string useful_F::send_to_arduino_clock (thread_data *my_data_logic, std::string msg){
9
5
    return "return test";
10
5
}
11
std::string useful_F::l_send_file(std::string path, std::string find, bool reverse )
12
3
{
13
3
    return "return test in l_send_file()";
14
3
}
15
16
1
std::string LCD_c::getData(){
17
1
    return " data test";
18
1
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/command_ip.cpp
Line
Count
Source
1
#include "command_ip.h"
2
3
command_ip::command_ip(const std::string &name):command(name)
4
8
{
5
8
}
6
7
std::string command_ip::execute(std::vector<std::string> &v, thread_data *my_data)
8
1
{
9
1
    return "iDom server IP: " +my_data->server_settings->SERVER_IP;
10
1
}
11
12
std::string command_ip::help()
13
1
{
14
1
    return "ip - show server IP address\n";
15
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/files_tree/files_tree.cpp
Line
Count
Source (jump to first uncovered line)
1
#include "files_tree.h"
2
3
bool comper (const movie_database & a , const movie_database& b)
4
212
{
5
212
    return a.files_name < b.files_name;
6
212
}
7
files_tree::files_tree (const std::string& path, LCD_c *mainLCD_PTR):database_path(path),w_serial( "([Ss]\\d{1,3}[Ee]\\d{1,3})")
8
9
12
{
10
12
    //database_path = path;
11
12
    mainLCD = mainLCD_PTR;
12
12
    //tree_stack.push(database_path);
13
12
    i_stack.push(0);
14
12
    i = 0;
15
12
    get_list(database_path);
16
12
}
17
bool files_tree::is_file() const
18
3
{
19
3
    return movie_database_vector[i].is_file;
20
3
}
21
22
void files_tree::next()
23
3
{   
24
3
    ++i;
25
3
    ////std::cout << " dodaje " << i << std::endl;
26
3
    if (get_vector_size() == i ){
27
1
        i=0;
28
1
    }
29
3
}
30
31
void files_tree::previous()
32
5
{
33
5
    --i;
34
5
    ////std::cout << " odejmuje " << i << std::endl;
35
5
36
5
    if ( i <0 )
37
5
    {
38
2
        i=get_vector_size()-1;
39
2
    }
40
5
}
41
42
int files_tree::get_vector_size () const
43
5
{
44
5
    return movie_database_vector.size();
45
5
}
46
void files_tree::vector_clear ()
47
14
{
48
14
    movie_database_vector.clear();
49
14
}
50
int files_tree::get_i()
51
1
{ if (i_stack.size() >1 ) {
52
1
        int i = i_stack.top();
53
1
        i_stack.pop();
54
1
        return i;
55
1
    }
56
1
    else
57
1
        return 0;
58
1
}
59
60
void files_tree::enter_dir()
61
1
{
62
1
    i_stack.push(i); // wpisuje na stos kolejna wersje licznika i
63
1
64
1
    if (movie_database_vector[i].is_file == false) {
65
1
        get_list (movie_database_vector[i].path);
66
1
        i=0;
67
1
    }
68
1
69
1
}
70
void files_tree::enter_dir(const std::string& path)
71
0
{ //tree_stack.push(path);
72
0
    get_list (path);
73
0
}
74
75
void files_tree::back_dir()
76
1
{
77
1
    if ( tree_stack.size() >1 ) {
78
1
        tree_stack.pop();
79
1
        std::string path = tree_stack.top();
80
1
        tree_stack.pop();
81
1
        i=get_i();
82
1
        get_list (path);
83
1
        return;
84
1
    }
85
1
    i=get_i();
86
0
87
0
    ////std::cout << " III ma teraz : " << i << std::endl;
88
0
    get_list (database_path);
89
0
    return;
90
1
}
91
92
std::string files_tree::show_list()
93
24
{
94
24
    //std::cout << "iteracja!!!!!!!!!!!!!!!!!!!!!!: " << i <<"rozmiar vectora : " << get_vector_size() << std::endl;
95
24
    if (movie_database_vector[i].is_file == true ) {
96
12
        //std::cout << "wypisuje sciezke pliku " << movie_database_vector[i].path <<" | " <<movie_database_vector[i].files_name.substr(0,16)<< std::endl;
97
12
98
12
        mainLCD->printString(true,0,0,movie_database_vector[i].files_name.substr(0,16));
99
12
        if( regex_search(movie_database_vector[i].path,result,w_serial) )
100
12
        {
101
12
            mainLCD->printString(false,10,1,movie_database_vector[i].files_name.substr( movie_database_vector[i].files_name.size()-4,movie_database_vector[i].files_name.size()));
102
12
            mainLCD->printString(false, 1,1,result[0]);
103
12
        }
104
12
        else
105
12
        {
106
0
            mainLCD->printString(false,10,1,movie_database_vector[i].files_name.substr( movie_database_vector[i].files_name.size()-4,movie_database_vector[i].files_name.size()));
107
0
        }
108
12
    }
109
24
    else {
110
12
        mainLCD->printString(true,0,0,movie_database_vector[i].files_name+"/");
111
12
    }
112
24
    return movie_database_vector[i].path;
113
24
}
114
115
14
void files_tree::get_list(std::string path) {
116
14
    tree_stack.push(path);
117
14
    vector_clear(); // czyscimy vector
118
14
    std::string path2 =path;
119
14
    std::string v_path ,tmp_string;
120
14
121
14
    if(sciezka = opendir( path.c_str() )) {
122
14
123
82
        while(( plik = readdir( sciezka ) ) )
124
68
        {
125
68
            path2 =path;
126
68
            if (static_cast<int>(plik->d_type) == 4 /*&& strcmp( plik->d_name, "..") && strcmp( plik->d_name, ".")*/)
127
68
            {
128
41
                temp.is_file=false;
129
41
            }
130
68
            else //if ( (int)plik->d_type == 8 && strcmp( plik->d_name, "..") && strcmp( plik->d_name, "."))
131
68
            {
132
27
                temp.is_file=true;
133
27
            }
134
68
135
68
            v_path= path2;
136
68
            v_path+="/";
137
68
            tmp_string.assign(plik->d_name);
138
68
            v_path+=tmp_string;
139
68
            temp.path =v_path;
140
68
            temp.files_name.assign(plik->d_name);
141
68
            movie_database_vector.push_back(temp);
142
68
        }// end while
143
14
        sort(movie_database_vector.begin(),movie_database_vector.end(), comper);
144
14
        closedir( sciezka );
145
14
    }
146
14
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/command_log.cpp
Line
Count
Source
1
#include "command_log.h"
2
3
command_log::command_log(const std::string &name):command(name)
4
8
{
5
8
}
6
7
std::string command_log::execute(std::vector<std::string> &v, thread_data *my_data)
8
8
{
9
8
    std::string msg;
10
16
    for (unsigned int i = 2; i < v.size(); ++i)
11
8
    {
12
8
        msg+=" ";
13
8
        msg+=v[i];
14
8
    }
15
8
    log_file_mutex.mutex_lock();
16
8
    log_file_cout <<"USER:- " << logLevel(v[1]) << msg <<std::endl;;
17
8
    log_file_mutex.mutex_unlock();
18
8
    return "DONE!";
19
8
}
20
21
std::string command_log::help()
22
1
{
23
1
    std::stringstream help;
24
1
    help << "log <logLevel> \"***TXT***\"- add *** to iDom logfile" << std::endl;
25
1
    return help.str();
26
1
}
27
28
logger_level command_log::logLevel(const std::string &level)
29
8
{
30
8
    if (level == "VERBOSE"){
31
1
        return VERBOSE;
32
1
    }
33
7
    else if (level == "DEBUG"){
34
1
        return DEBUG;
35
1
    }
36
6
    else if (level == "INFO"){
37
1
        return INFO;
38
1
    }
39
5
    else if (level == "WARNING"){
40
1
        return WARNING;
41
1
    }
42
4
    else if (level == "ERROR"){
43
1
        return ERROR;
44
1
    }
45
3
    else if (level == "FATAL"){
46
1
        return FATAL;
47
1
    }
48
2
    else if (level == "CRITICAL"){
49
1
        return CRITICAL;
50
1
    }
51
1
puts ("nie mam co wysetlic wale verbose");
52
1
        return VERBOSE;
53
1
54
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDom_server_OOP.h
Line
Count
Source
1
#ifndef GLOBAL_H
2
#define GLOBAL_H
3
4
#include <iostream>
5
#include <fstream>
6
#include <string>
7
#include <cstdlib>
8
#include <pthread.h>
9
#include <stdio.h>
10
#include <stdlib.h>
11
#include <sys/socket.h>
12
#include <sys/types.h>
13
#include <netinet/in.h>
14
#include <vector>
15
#include <thread>
16
#include <arpa/inet.h>
17
#include <netinet/in.h>
18
#include <unistd.h>
19
#include <sys/fcntl.h>
20
#include <unistd.h>
21
#include <errno.h>
22
#include <signal.h>
23
#include <time.h>
24
#include <wiringPi.h>
25
#include <chrono>
26
#include <array>
27
28
// MOJE BIBLIOTEKI
29
#include "KEY/key.h"
30
#include "logger/logger.hpp"
31
#include "files_tree/files_tree.h"
32
#include "menu_tree/menu_tree.h"
33
#include "LCD_c/lcd_c.h"
34
#include "command/command.h"
35
#include "../libs/event_counters/event_counters_handler.h"
36
#include "iDomTools/idomtools.h"
37
#include "iDomStatus/idomstatus.h"
38
#include "iDomSaveState/idom_save_state.h"
39
40
37
#define log_file_cout  f_log //std::cout zmien f_log na std::cout i bedzie wypisywac na ekran
41
16
#define log_file_mutex f_log
42
43
enum class iDomStateEnum{
44
    CLOSE = 0,
45
    RELOAD,
46
    ERROR,
47
    WORKING,
48
    HARD_RELOAD
49
};
50
51
namespace iDomConst
52
{
53
constexpr int MAX_CONNECTION = 10;
54
constexpr int FREE  = 1;
55
constexpr int RS232 = 11;
56
constexpr int CLOCK = 12;
57
constexpr int ok    = 0;
58
constexpr int GPIO_SPIK = 21;
59
constexpr int GPIO_PRINTER = 22;
60
constexpr int BUTTON_PIN = 25;
61
}
62
struct ALERT
63
{
64
    Clock time;
65
    STATE state = STATE::DEACTIVE;
66
    unsigned int fromVolume = 48;
67
    unsigned int toVolume = 58;
68
    unsigned int radioID = 8;
69
};
70
71
extern std::string _logfile;
72
extern Logger log_file_mutex;
73
extern std::string buffer;
74
75
enum class TEMPERATURE_STATE;
76
enum class PILOT_KEY;
77
78
struct MPD_info{
79
    std::string title   = "NULL";
80
    std::string radio   = "NULL";
81
    std::string artist  = "NULL";
82
    int volume = 0;
83
    bool isPlay = false;
84
    int currentSongID = 0;
85
    std::vector <std::string> songList = {"NULL"};
86
};
87
struct s_pointer{
88
    unsigned int *ptr_who;
89
    int32_t *ptr_buf;
90
};
91
92
struct Thread_array_struc {
93
    std::thread thread;
94
    std::thread::id thread_ID = std::thread::id(0);
95
    std::string thread_name;
96
    int thread_socket = 0;
97
};
98
99
struct address_another_servers {
100
    int id;
101
    std::string SERVER_IP;
102
};
103
104
struct FTP_SERVER{
105
    std::string URL;
106
    std::string user;
107
    std::string pass;
108
};
109
struct iDOM_STATE{
110
    STATE houseState = STATE::UNDEFINE;
111
112
};
113
114
struct config{
115
    std::string portRS232;
116
    std::string portRS232_clock;
117
    std::string BaudRate;
118
    std::string RFLinkPort;
119
    std::string RFLinkBaudRate;
120
    int PORT;
121
    std::string SERVER_IP;
122
    std::string MPD_IP;
123
    std::string MOVIES_DB_PATH;
124
    std::string MENU_PATH;
125
    std::string THREAD_MPD   = "NULL";
126
    std::string THREAD_IRDA  = "NULL";
127
    std::string THREAD_CRON  = "NULL";
128
    std::string THREAD_RS232 = "NULL";
129
    std::string THREAD_DUMMY = "NULL";
130
    std::string TS_KEY= " gg ";
131
    std::string cameraLedON = "";
132
    std::string cameraLedOFF ="";
133
    std::string cameraURL="";
134
    std::string facebookAccessToken = "";
135
    std::string viberToken = "NULL";
136
    std::string viberAvatar;
137
    std::vector <std::string> viberReceiver;
138
    std::string viberSender;
139
    std::string radio433MHzConfigFile;
140
    std::string omxplayerFile = "NULL";
141
    int ID_server = 0;
142
    int v_delay;
143
    bool encrypted = true;
144
145
    FTP_SERVER ftpServer;
146
    std::string lightningApiURL = "NULL";
147
    std::string saveFilePath = "NULL";
148
};
149
150
struct LED_Strip{
151
    std::string from;
152
    std::string to;
153
    std::string R;
154
    std::string G;
155
    std::string B;
156
    std::string colorName;
157
158
    LED_Strip (int from, int to, int r, int g, int b, std::string colorName = "NULL"):from(std::to_string(from)),
159
        to(std::to_string(to)),
160
        R(std::to_string(r)),
161
        G(std::to_string(g)),
162
        B(std::to_string(b)),
163
        colorName(colorName)
164
    {
165
166
    }
167
    LED_Strip (const std::string& from,
168
               const std::string& to,
169
               const std::string& r,
170
               const std::string& g,
171
               const std::string& b,
172
               const std::string& colorName = "NULL"):
173
        from(from),
174
        to(to),
175
        R(r),
176
        G(g),
177
        B(b),
178
        colorName(colorName)
179
    {
180
181
    }
182
183
    void set (const std::string& from,
184
              const std::string& to,
185
              const std::string& r,
186
              const std::string& g,
187
              const std::string& b,
188
              const std::string& colorName = "NULL")
189
    {
190
        this->from =from;
191
        this->to = to;
192
        R = r;
193
        G = g;
194
        B = b;
195
        this->colorName =colorName;
196
    }
197
198
    void set (int from, int to, int r, int g, int b, std::string colorName = "NULL"){
199
        this->from = std::to_string(from);
200
        this->to = std::to_string(to);
201
        R = std::to_string(r);
202
        G = std::to_string(g);
203
        B = std::to_string(b);
204
        this->colorName =colorName;
205
    }
206
207
    std::string getColorName() const{
208
        return colorName;
209
    }
210
211
    std::string get(unsigned int _from, unsigned int _to) const{
212
        if (_from != 0 || _to != 60){
213
            return "LED:["+std::to_string(_from)+"-"+std::to_string(_to)+"-"+R+"-"+G+"-"+B+"];";
214
        }
215
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
216
    }
217
218
    std::string makeCommand(const std::string& from,
219
                            const std::string& to,
220
                            const std::string& R,
221
                            const std::string& G,
222
                            const std::string& B){
223
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
224
    }
225
};
226
227
struct pilot_led{
228
    unsigned int counter=0;
229
    std::vector<LED_Strip> colorLED   = { LED_Strip(1,60,237,145,33 ,"carrot orange"),
230
                                          LED_Strip(1,60,255,0,0    ,"red"),
231
                                          LED_Strip(1,60,0,255,0    ,"green"),
232
                                          LED_Strip(1,60,0,0,255    ,"blue"),
233
                                          LED_Strip(1,60,255,255,255,"white"),
234
                                          LED_Strip(1,60,255,255,0  ,"yellow"),
235
                                          LED_Strip(1,60,0,255,255  ,"cyan"),
236
                                          LED_Strip(1,60,255,0,255  ,"magenta")
237
                                        };
238
};
239
240
class command; // for struc thread_data req
241
class iDomTOOLS;
242
class RADIO_EQ_CONTAINER;
243
class RFLinkHandler;
244
245
struct thread_data{
246
    int s_client_sock;
247
    struct sockaddr_in from;
248
    struct config *server_settings = NULL;
249
    struct s_pointer pointer;
250
    LCD_c *mainLCD = NULL;
251
    files_tree *main_tree = NULL;
252
    menu_tree *main_MENU = NULL;
253
    iDomTOOLS *main_iDomTools = NULL;
254
    RFLinkHandler *main_RFLink = NULL;
255
    std::array<Thread_array_struc, iDomConst::MAX_CONNECTION> *main_THREAD_arr = NULL;
256
    time_t start;
257
    time_t now_time;
258
    int sleeper;
259
    std::map <std::string, std::unique_ptr <KEY> > key_map;
260
    MPD_info *ptr_MPD_info = NULL;
261
    pilot_led * ptr_pilot_led = NULL;
262
    std::map <std::string, std::unique_ptr<command> >* commandMapPtr = NULL;
263
    event_counters_handler myEventHandler;
264
    std::string encriptionKey = "40%";
265
    iDomSTATUS *main_iDomStatus;
266
    iDOM_STATE idom_all_state;
267
    ALERT alarmTime;
268
    std::shared_ptr<RADIO_EQ_CONTAINER> main_REC;
269
    iDomStateEnum iDomProgramState = iDomStateEnum::WORKING;
270
};
271
272
struct thread_data_rs232{
273
    std::string portRS232;
274
    std::string portRS232_clock;
275
    std::string BaudRate;
276
    struct s_pointer pointer;
277
};
278
279
#endif // GLOBAL_H
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/command_mpd.cpp
Line
Count
Source
1
#include "command_mpd.h"
2
#include "../../blockQueue/blockqueue.h"
3
#include "../../functions/functions.h"
4
5
command_mpd::command_mpd(const std::string &name) :command(name)
6
16
{
7
16
}
8
9
std::string command_mpd::execute(std::vector<std::string> &v, thread_data *my_data)
10
14
{
11
14
    std::string str_buf;
12
14
13
14
    if (v[1]=="start")
14
2
    {
15
2
        if (v.size()>2)
16
1
        {
17
1
            int id = std::stoi(v[2]);
18
1
            if (id > 0)
19
1
            {
20
1
                iDomTOOLS::MPD_play(my_data,id);
21
1
                useful_F::sleep(1);
22
1
                str_buf = my_data->ptr_MPD_info->songList[id-1];
23
1
            }
24
1
        }
25
1
        else
26
1
        {
27
1
            iDomTOOLS::MPD_play(my_data);
28
1
            useful_F::sleep(1);
29
1
            str_buf=my_data->ptr_MPD_info->title;
30
1
        }
31
2
        my_data->main_iDomTools->saveState_iDom();
32
2
    }
33
12
    else if (v[1]=="stop")
34
1
    {
35
1
        iDomTOOLS::MPD_stop();
36
1
        str_buf="stoped!";
37
1
        my_data->main_iDomTools->saveState_iDom();
38
1
    }
39
11
    else if (v[1]=="next")
40
1
    {
41
1
        iDomTOOLS::MPD_next();
42
1
        useful_F::sleep(1);
43
1
        str_buf = my_data->ptr_MPD_info->radio + " : "+ my_data->ptr_MPD_info->title;
44
1
    }
45
10
    else if (v[1]=="prev")
46
1
    {
47
1
        iDomTOOLS::MPD_prev();
48
1
        useful_F::sleep(1);
49
1
        str_buf=my_data->ptr_MPD_info->radio+ " : "+ my_data->ptr_MPD_info->title;
50
1
    }
51
9
    else if (v[1]=="pause")
52
1
    {
53
1
        iDomTOOLS::MPD_pause();
54
1
        str_buf="paused!";
55
1
    }
56
8
    else if (v[1]=="volume")
57
4
    {
58
4
        if (v[2]=="up")
59
1
        {
60
1
            iDomTOOLS::MPD_volumeUp();
61
1
        }
62
3
        else if (v[2]=="down")
63
1
        {
64
1
            iDomTOOLS::MPD_volumeDown();
65
1
        }
66
2
        else
67
2
        {
68
2
            int vol = std::stoi(v[2]);
69
2
            if (vol >0 && vol <100)
70
1
            {
71
1
                iDomTOOLS::MPD_volumeSet(my_data,vol);
72
1
            }
73
2
        }
74
4
        //sleep(1);
75
4
        str_buf=std::to_string(my_data->ptr_MPD_info->volume);
76
4
    }
77
4
    else if (v[1]=="get")
78
2
    {
79
2
        if(v[2]=="volume")
80
1
        {
81
1
            str_buf=std::to_string(my_data->ptr_MPD_info->volume);
82
1
        }
83
1
        else if (v[2]=="info")
84
1
        {
85
1
            str_buf = my_data->ptr_MPD_info->radio + " : "+ my_data->ptr_MPD_info->title;
86
1
        }
87
2
    }
88
2
    else if (v[1]=="list")
89
1
    {
90
1
        for (auto i : my_data->ptr_MPD_info->songList)
91
3
            str_buf += i+"\n";
92
1
    }
93
1
    else
94
1
    {
95
1
        str_buf = "unknown parameter " + v[1];
96
1
    }
97
14
    return str_buf;
98
14
}
99
100
std::string command_mpd::help()
101
1
{
102
1
    std::stringstream help;
103
1
    help << "MPD - for control music player:" << std::endl;
104
1
    help << "parameter:" << std::endl;
105
1
    help << "\tstart - play music" << std::endl;
106
1
    help << "\tstop  - stop music" << std::endl;
107
1
    help << "\tpause - pause music" << std::endl;
108
1
    help << "\tnext  - next song" << std::endl;
109
1
    help << "\tprev  - previous song" << std::endl;
110
1
    help << "\tlist  - show playlist" << std::endl;
111
1
    help << "\tget volume - get volume %" << std::endl;
112
1
    help << "\tget info - get info about current song" << std::endl;
113
1
    help << "\tvolume up/down - increase/decrease volume 1%" << std::endl;
114
1
    return help.str();
115
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/logger/logger.hpp
Line
Count
Source
1
/*
2
 * logger.hpp
3
 *
4
 *
5
 * Logger Library Header
6
 *
7
 *
8
 * Copyright (C) 2013-2014  Bryant Moscon - bmoscon@gmail.com
9
 *
10
 * Permission is hereby granted, free of charge, to any person obtaining a copy
11
 * of this software and associated documentation files (the "Software"), to
12
 * deal in the Software without restriction, including without limitation the
13
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
14
 * sell copies of the Software, and to permit persons to whom the Software is
15
 * furnished to do so, subject to the following conditions:
16
 *
17
 * 1. Redistributions of source code must retain the above copyright notice,
18
 *    this list of conditions, and the following disclaimer.
19
 *
20
 * 2. Redistributions in binary form must reproduce the above copyright notice,
21
 *    this list of conditions and the following disclaimer in the documentation
22
 *    and/or other materials provided with the distribution, and in the same
23
 *    place and form as other copyright, license and disclaimer information.
24
 *
25
 * 3. The end-user documentation included with the redistribution, if any, must
26
 *    include the following acknowledgment: "This product includes software
27
 *    developed by Bryant Moscon (http://www.bryantmoscon.org/)", in the same
28
 *    place and form as other third-party acknowledgments. Alternately, this
29
 *    acknowledgment may appear in the software itself, in the same form and
30
 *    location as other such third-party acknowledgments.
31
 *
32
 * 4. Except as contained in this notice, the name of the author, Bryant Moscon,
33
 *    shall not be used in advertising or otherwise to promote the sale, use or
34
 *    other dealings in this Software without prior written authorization from
35
 *    the author.
36
 *
37
 *
38
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
41
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
42
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
44
 * THE SOFTWARE.
45
 *
46
 */
47
#ifndef __LOGGER__
48
#define __LOGGER__
49
50
#include <fstream>
51
#include <cassert>
52
#include <ctime>
53
#include <sstream>
54
55
// Log levels
56
typedef enum {
57
    US =0,
58
    VERBOSE,
59
    DEBUG,
60
    INFO,
61
    WARNING,
62
    ERROR,
63
    CRITICAL,
64
    FATAL
65
} logger_level;
66
67
class Logger : public std::ostringstream {
68
public:
69
70
    explicit Logger(const char *f);
71
    explicit Logger(const std::string& f);
72
    Logger (const Logger &);
73
    Logger &operator= (const Logger &);
74
    ~Logger();
75
    static pthread_mutex_t mutex_log;
76
77
    void set_level(const logger_level& level);
78
    void flush();
79
    void mutex_lock();
80
    void mutex_unlock();
81
82
    template <typename T>
83
    Logger& operator<<(const T& t)
84
10
    {
85
10
        *static_cast<std::ostringstream *>(this) << t;
86
10
        return (*this);
87
10
    }
Unexecuted instantiation: _ZN6LoggerlsIA44_cEERS_RKT_
_ZN6LoggerlsIA23_cEERS_RKT_
Line
Count
Source
84
4
    {
85
4
        *static_cast<std::ostringstream *>(this) << t;
86
4
        return (*this);
87
4
    }
_ZN6LoggerlsIA14_cEERS_RKT_
Line
Count
Source
84
6
    {
85
6
        *static_cast<std::ostringstream *>(this) << t;
86
6
        return (*this);
87
6
    }
Unexecuted instantiation: _ZN6LoggerlsIA27_cEERS_RKT_
Unexecuted instantiation: _ZN6LoggerlsIiEERS_RKT_
88
89
    Logger& operator<<(const logger_level& level);
90
    typedef Logger& (* LoggerManip)(Logger&);
91
    Logger& operator<<(LoggerManip m);
92
93
private:
94
    std::string get_time() const;
95
    inline const char* level_str(const logger_level& level);
96
public:
97
    std::ofstream _file;
98
private:
99
    std::ostream& _log;
100
    logger_level _level;
101
    logger_level _line_level;
102
};
103
104
105
namespace std { 
106
inline Logger& endl(Logger& out)
107
{
108
    out.put('\n');
109
    out.flush();
110
    return (out);
111
}
112
}// end namespace std
113
114
#endif
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/command_ok.cpp
Line
Count
Source
1
#include "command_ok.h"
2
3
command_ok::command_ok(const std::string &name):command(name)
4
8
{
5
8
}
6
7
std::string command_ok::execute(std::vector<std::string> &v, thread_data *my_data)
8
2
{
9
2
    return "\nEND\n";
10
2
}
11
12
std::string command_ok::help()
13
2
{
14
2
    return "ok - confirmation msg server response: END \n";
15
2
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/functions/functions2.cpp
Line
Count
Source (jump to first uncovered line)
1
#include <iostream>
2
#include <fstream>
3
#include <regex>
4
#include <iterator>
5
#include <vector>
6
7
#include "functions.h"
8
#include "../thread_functions/iDom_thread.h"
9
10
23
std::vector<std::string> useful_F::split(const std::string& s, char separator ){
11
23
    std::vector<std::string> output;
12
23
    std::string::size_type prev_pos = 0, pos = 0;
13
23
14
53
    while((pos = s.find(separator, pos)) != std::string::npos)
15
30
    {
16
30
        std::string substring( s.substr(prev_pos, pos-prev_pos) );
17
30
        output.push_back(substring);
18
30
        prev_pos = ++pos;
19
30
    }
20
23
    try
21
23
    {
22
23
        output.push_back(s.substr(prev_pos, pos-prev_pos)); // Last word
23
23
    }
24
23
    catch (...)
25
23
    {
26
0
        log_file_mutex.mutex_lock();
27
0
        log_file_cout << CRITICAL << "wyjatek substr() w useful_F::split() !!!!!!"<< std::endl;
28
0
        log_file_mutex.mutex_unlock();
29
0
    }
30
23
    return output;
31
23
}
32
thread_data* useful_F::myStaticData = std::nullptr_t();
33
void useful_F::setStaticData(thread_data *my_dataPtr)
34
1
{
35
1
    myStaticData = my_dataPtr;
36
1
}
37
38
5
void useful_F::tokenizer ( std::vector <std::string> &command, std::string separator, std::string &text){
39
5
    std::string temp;
40
5
41
5
    for(char n: text)
42
44
    { // the initializer may be an array
43
44
        bool is_sep = false;
44
44
        for(char m: separator)
45
119
        {
46
119
            if (n == m)
47
119
                is_sep = true;
48
119
        }
49
44
        if (is_sep == false)
50
44
            temp += n;
51
44
        else
52
44
        {
53
5
            if (!temp.empty())
54
5
            {
55
5
                command.push_back( temp);
56
5
                temp = "";
57
5
            }
58
5
        }
59
44
    }
60
5
    if (!temp.empty())
61
5
        command.push_back(temp);
62
5
63
5
    if (command.size() == 0)
64
5
        throw std::string("command empty");
65
5
}
66
67
////// watek sleeper
68
void useful_F::sleeper_mpd (thread_data *my_data, const std::string& threadName)
69
3
{
70
3
    unsigned int t = 60/my_data->sleeper;
71
3
    unsigned int k = 0;
72
3
73
16
    for (; my_data->sleeper >0; my_data->sleeper-- )
74
13
    {
75
13
        useful_F::sleep(60);
76
13
        k += t;
77
13
        my_data->main_iDomTools->ledClear(0,k);
78
13
    }
79
3
    my_data->main_iDomTools->ledOFF();
80
3
    my_data->main_iDomTools->MPD_stop();
81
3
    my_data->main_iDomTools->turnOff433MHzSwitch("listwa");
82
3
83
3
    log_file_mutex.mutex_lock();
84
3
    log_file_cout << INFO<< "zaczynam procedure konca watku " << threadName << std::endl;
85
3
    log_file_mutex.mutex_unlock();
86
3
87
3
    iDOM_THREAD::stop_thread(threadName,my_data);
88
3
89
3
    log_file_mutex.mutex_lock();
90
3
    log_file_cout << INFO<< "koniec watku SLEEP_MPD" << std::endl;
91
3
    log_file_mutex.mutex_unlock();
92
3
}
93
94
///////////////////////////////////////////////////////////////////////////////////////////////////// watek kodi
95
void useful_F::kodi (thread_data *my_data, const std::string& threadName)
96
2
{
97
2
    log_file_mutex.mutex_lock();
98
2
    log_file_cout << INFO<< "start wątku "<<threadName << std::endl;
99
2
    log_file_mutex.mutex_unlock();
100
2
101
2
    my_data->mainLCD->set_print_song_state(100);
102
2
    my_data->mainLCD->printString(false,2,1,"  KODI");
103
2
104
2
    my_data->main_iDomStatus->setObjectState("KODI",STATE::ACTIVE);
105
2
    //status mpd
106
2
    STATE musicState = my_data->main_iDomStatus->getObjectState("music");
107
2
    // status glosnikow
108
2
    STATE speakersState = my_data->main_iDomStatus->getObjectState("speakers");
109
2
110
2
    if (musicState != STATE::STOP)
111
2
        my_data->main_iDomTools->MPD_pause();
112
2
    if (speakersState != STATE::ON)
113
2
        my_data->main_iDomTools->turnOnSpeakers();
114
2
    //system
115
2
116
2
    int ret = useful_F::runLinuxCommand("runuser -u pi kodi");
117
2
118
2
    if(ret != 0)
119
2
    {
120
0
        log_file_mutex.mutex_lock();
121
0
        log_file_cout << CRITICAL<< "kodi zamkniete z błędem "<<ret << std::endl;
122
0
        log_file_mutex.mutex_unlock();
123
0
    }
124
2
    //przywracanie danych
125
2
126
2
    if(musicState == STATE::PLAY)
127
2
        my_data->main_iDomTools->MPD_play(my_data);
128
2
    else
129
2
        my_data->main_iDomTools->turnOffSpeakers();
130
2
    //koniec
131
2
132
2
    my_data->main_iDomStatus->setObjectState("KODI",STATE::DEACTIVE);
133
2
    my_data->mainLCD->set_print_song_state(0);
134
2
    iDOM_THREAD::stop_thread("kodi smartTV",my_data);
135
2
}
136
std::string useful_F::RSHash(const std::string& data, unsigned int b, unsigned int a)
137
4
{
138
4
    time_t act_time;
139
4
    struct tm * act_date;
140
4
    time(&act_time);
141
4
    act_date = localtime(&act_time);
142
4
    char buffer[10];
143
4
    strftime(buffer,10,"%M%H%w",act_date);
144
4
    std::string str(buffer);
145
4
    str+=data;
146
4
    unsigned int hash = 0;
147
4
148
56
    for(std::size_t i = 0; i < str.length(); i++)
149
52
    {
150
52
        hash = hash * a + str[i];
151
52
        a = a * b;
152
52
    }
153
4
    return std::to_string((hash & 0x7FFFFFFF));
154
4
}
155
156
int useful_F::findFreeThreadSlot(std::array<Thread_array_struc, iDomConst::MAX_CONNECTION> *array)
157
5
{
158
24
    for (std::size_t i = 0; i< array->size(); ++i)
159
23
    {
160
23
        if (array->at(i).thread_socket == 0)
161
23
            return static_cast<int>(i);
162
23
    }
163
5
    puts("return -1");
164
1
    return -1;
165
5
}
166
167
std::string useful_F::sek_to_uptime(long long secy )
168
2
{
169
2
    const int min = 60; //s
170
2
    const int houry = 3600; //s
171
2
    const int day = 86400; //s
172
2
    int number_day, number_hour, number_min, number_sec;
173
2
    int temp1, temp2, temp3;
174
2
    number_day = secy / day;
175
2
    std::stringstream text;
176
2
    text << "\n" << number_day << " day ";
177
2
    temp1 = secy % day;
178
2
    number_hour = temp1 / houry;
179
2
    text << number_hour << " hours ";
180
2
    temp2 = temp1 % houry;
181
2
    number_min = temp2 / min;
182
2
    text << number_min << " minutes ";
183
2
    temp3 = temp2 % min;
184
2
    number_sec = temp3;
185
2
    text << number_sec << " seconds";
186
2
    return text.str();
187
2
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/command_program.cpp
Line
Count
Source
1
#include "command_program.h"
2
#include "../../functions/functions.h"
3
#include "../../433MHz/RFLink/rflinkhandler.h"
4
5
command_program::command_program(const std::string &name):command(name)
6
16
{
7
16
}
8
9
std::string command_program::execute(std::vector<std::string> &v, thread_data *my_data)
10
10
{
11
10
    std::string ret = help();
12
10
    if (v.size() <2 )
13
1
    {
14
1
        return "what?\n" + help();
15
1
    }
16
9
    if (v[1] == "stop")
17
2
    {
18
2
        std::string s ="close server";
19
2
        useful_F::send_to_arduino_clock(my_data, "STOP");
20
2
        iDomTOOLS::MPD_stop();
21
2
        my_data->iDomProgramState = iDomStateEnum::CLOSE;
22
2
        my_data->main_iDomTools->saveState_iDom();
23
2
        throw s;
24
2
    }
25
7
    if (v.size() < 3 )
26
1
    {
27
1
        return "add more paramiters";
28
1
    }
29
6
    if(v[1] == "reload" && v[2] == "soft"){
30
1
        std::string s ="close server";
31
1
        useful_F::send_to_arduino_clock(my_data, "RELO");
32
1
        iDomTOOLS::MPD_stop();
33
1
        my_data->iDomProgramState = iDomStateEnum::RELOAD;
34
1
        my_data->main_iDomTools->saveState_iDom();
35
1
        throw s;
36
1
    }
37
5
    else if(v[1] == "reload" && v[2] == "hard")
38
1
    {
39
1
        std::string s ="close server";
40
1
        useful_F::send_to_arduino_clock(my_data, "UPAD");
41
1
        iDomTOOLS::MPD_stop();
42
1
        my_data->iDomProgramState = iDomStateEnum::HARD_RELOAD;
43
1
        my_data->main_iDomTools->saveState_iDom();
44
1
        throw s;
45
1
    }
46
4
    else if(v[1] == "clear" && v[2] == "ram")
47
1
    {
48
1
        useful_F::runLinuxCommand("sync; echo 3 > /proc/sys/vm/drop_caches");
49
1
        ret = "ram has beed freed";
50
1
    }
51
3
    else if(v[1] == "debuge" && v[2] == "variable")
52
1
    {
53
1
        std::stringstream r;
54
1
       r << "my_data->alarmTime.fromVolume \t" << my_data->alarmTime.fromVolume <<std::endl;
55
1
        r << "my_data->alarmTime.radioID \t" << my_data->alarmTime.radioID <<std::endl;
56
1
        r << "my_data->alarmTime.state \t" << stateToString( my_data->alarmTime.state) <<std::endl;
57
1
        r << "my_data->alarmTime.time \t" << my_data->alarmTime.time.getString() <<std::endl;
58
1
        r << "my_data->alarmTime.toVolume \t" << my_data->alarmTime.toVolume <<std::endl;
59
1
        r << std::endl;
60
1
        r << "my_data->encriptionKey \t" << my_data->encriptionKey <<std::endl;
61
1
        r << std::endl;
62
1
        r << "my_data->server_settings->BaudRate \t" << my_data->server_settings->BaudRate <<std::endl;
63
1
        r << "my_data->server_settings->cameraLedOFF \t" << my_data->server_settings->cameraLedOFF <<std::endl;
64
1
        r << "my_data->server_settings->cameraLedON \t" << my_data->server_settings->cameraLedON <<std::endl;
65
1
        r << "my_data->server_settings->cameraURL \t" << my_data->server_settings->cameraURL <<std::endl;
66
1
        r << "my_data->server_settings->encrypted \t" << my_data->server_settings->encrypted <<std::endl;
67
1
        r << "my_data->server_settings->facebookAccessToken \t" << my_data->server_settings->facebookAccessToken <<std::endl;
68
1
        r << "my_data->server_settings->ftpServer.URL \t" << my_data->server_settings->ftpServer.URL <<std::endl;
69
1
        r << "my_data->server_settings->ftpServer.user \t" << my_data->server_settings->ftpServer.user <<std::endl;
70
1
        r << "my_data->server_settings->ID_server \t" << my_data->server_settings->ID_server <<std::endl;
71
1
        r << "my_data->server_settings->lightningApiURL \t" << my_data->server_settings->lightningApiURL <<std::endl;
72
1
        r << "my_data->server_settings->MENU_PATH \t" << my_data->server_settings->MENU_PATH<<std::endl;
73
1
        r << "my_data->server_settings->MOVIES_DB_PATH \t" << my_data->server_settings->MOVIES_DB_PATH<<std::endl;
74
1
        r << "my_data->server_settings->MPD_IP \t" << my_data->server_settings->MPD_IP<<std::endl;
75
1
        r << "my_data->server_settings->omxplayerFile \t" << my_data->server_settings->omxplayerFile<<std::endl;
76
1
        r << "my_data->server_settings->PORT \t" << my_data->server_settings->PORT<<std::endl;
77
1
        r << "my_data->server_settings->portRS232 \t" << my_data->server_settings->portRS232<<std::endl;
78
1
        r << "my_data->server_settings->portRS232_clock \t" << my_data->server_settings->portRS232_clock<<std::endl;
79
1
        r << "my_data->server_settings->radio433MHzConfigFile \t" << my_data->server_settings->radio433MHzConfigFile<<std::endl;
80
1
        r << "my_data->server_settings->RFLinkBaudRate \t" << my_data->server_settings->RFLinkBaudRate<<std::endl;
81
1
        r << "my_data->server_settings->RFLinkPort \t" << my_data->server_settings->RFLinkPort<<std::endl;
82
1
        r << "my_data->server_settings->saveFilePath \t" << my_data->server_settings->saveFilePath<<std::endl;
83
1
        r << "my_data->server_settings->SERVER_IP \t" << my_data->server_settings->SERVER_IP<<std::endl;
84
1
        r << "my_data->server_settings->THREAD_CRON \t" << my_data->server_settings->THREAD_CRON<<std::endl;
85
1
        r << "my_data->server_settings->THREAD_DUMMY \t" << my_data->server_settings->THREAD_DUMMY<<std::endl;
86
1
        r << "my_data->server_settings->THREAD_IRDA \t" << my_data->server_settings->THREAD_IRDA<<std::endl;
87
1
        r << "my_data->server_settings->THREAD_MPD \t" << my_data->server_settings->THREAD_MPD<<std::endl;
88
1
        r << "my_data->server_settings->THREAD_RS232 \t" << my_data->server_settings->THREAD_RS232<<std::endl;
89
1
        r << "my_data->server_settings->TS_KEY \t" << my_data->server_settings->TS_KEY<<std::endl;
90
1
        r << "my_data->server_settings->viberAvatar \t" << my_data->server_settings->viberAvatar<<std::endl;
91
1
        r << "my_data->server_settings->viberReceiver.at(0) \t" << my_data->server_settings->viberReceiver.at(0)<<std::endl;
92
1
        r << "my_data->server_settings->viberSender \t" << my_data->server_settings->viberSender<<std::endl;
93
1
        r << "my_data->server_settings->viberToken \t" << my_data->server_settings->viberToken<<std::endl;
94
1
        r << "my_data->server_settings->v_delay \t" << my_data->server_settings->v_delay<<std::endl;
95
1
        r << std::endl;
96
1
        r << "my_data->server_settings->sleeper \t" << my_data->sleeper<<std::endl;
97
1
        r << std::endl;
98
1
        r << "my_data->iDomProgramState \t" << static_cast<int>(my_data->iDomProgramState)<<std::endl;
99
1
        r << std::endl;
100
1
        r << "my_data->main_iDomStatus \t" << my_data->main_iDomStatus->getAllObjectsStateString()<<std::endl;
101
1
        r << std::endl;
102
1
        r << "my_data->idom_all_state.houseState \t" <<stateToString(my_data->idom_all_state.houseState)<<std::endl;
103
1
        r << std::endl;
104
1
        r << "my_data->now_time \t" << my_data->now_time<<std::endl;
105
1
        r << "my_data->start - time \t" << my_data->start<<std::endl;
106
1
        r << std::endl;
107
1
        r << "my_data->pointer.ptr_buf \t" << my_data->pointer.ptr_buf<<std::endl;
108
1
        r << "my_data->pointer.ptr_who \t" << my_data->pointer.ptr_who<<std::endl;
109
1
110
1
        r << std::endl;
111
1
        r << "my_data->ptr_MPD_info->artist \t" << my_data->ptr_MPD_info->artist<<std::endl;
112
1
        r << "my_data->ptr_MPD_info->currentSongID \t" << my_data->ptr_MPD_info->currentSongID<<std::endl;
113
1
        r << "my_data->ptr_MPD_info->isPlay \t" << my_data->ptr_MPD_info->isPlay<<std::endl;
114
1
        r << "my_data->ptr_MPD_info->radio \t" << my_data->ptr_MPD_info->radio<<std::endl;
115
1
        r << "my_data->ptr_MPD_info->songList.at(0) \t" << my_data->ptr_MPD_info->songList.at(0)<<std::endl;
116
1
        r << "my_data->ptr_MPD_info->title \t" << my_data->ptr_MPD_info->title<<std::endl;
117
1
        r << "my_data->ptr_MPD_info->volume \t" << my_data->ptr_MPD_info->volume<<std::endl;
118
1
119
1
        r << std::endl;
120
1
        r << "my_data->main_RFLink->okTime \t" << my_data->main_RFLink->okTime<<std::endl;
121
1
        r << "my_data->main_RFLink->pingTime \t" << my_data->main_RFLink->pingTime<<std::endl;
122
1
123
1
        r << std::endl;
124
1
        r << "my_data->mainLCD-> \t" << my_data->mainLCD->getData() <<std::endl;
125
1
126
1
        r << "END.";
127
1
        ret = r.str();
128
1
    }
129
2
    else if(v[1] == "raspberry")
130
1
    {
131
1
        int i = useful_F::runLinuxCommand(v[2].c_str());
132
1
        ret = "command done with exitcode: " + std::to_string(i);
133
1
    }
134
1
    else
135
1
    {
136
1
        ret = " what? - "+ v[1];
137
1
    }
138
6
    return ret;
139
6
}
140
141
std::string command_program::help()
142
12
{
143
12
    std::stringstream help;
144
12
    help << "program stop - close iDom server"<< std::endl;
145
12
    help << "program reload soft - reload iDom server" << std::endl;
146
12
    help << "program reload hard - reload iDom server" << std::endl;
147
12
    help << "program clear ram   - reload iDom server" << std::endl;
148
12
    help << "program debuge variable - show value iDom server variable" << std::endl;
149
12
    help << "program raspberry <command> - put command to raspberry " << std::endl;
150
12
    return help.str();
151
12
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/functions/tests/functions_BT.cpp
Line
Count
Source
1
#include <gtest/gtest.h>
2
#include "../functions.h"
3
#include "../../RADIO_433_eq/radio_433_eq.h"
4
#include "../../iDomTools/test/iDomTools_fixture.h"
5
6
class functions_fixture : public iDomTOOLS_ClassTest{
7
8
};
9
10
void useful_F::sleep(int sec)
11
25
{
12
25
    std::cout << "sleep() sec: " << sec <<std::endl;
13
25
}
14
15
TEST(functions_, tokenizer)
16
1
{
17
1
     std::string test_msg = "one=two three";
18
1
     std::vector<std::string> test_v;
19
1
20
1
     EXPECT_EQ(test_v.size(), 0);
21
1
     useful_F::tokenizer(test_v,"= ",test_msg);
22
1
23
1
     EXPECT_EQ(test_v.size(),3);
24
1
     EXPECT_STREQ(test_v.at(2).c_str(),"three");
25
1
}
26
27
TEST(functions_, sekToUptime)
28
1
{
29
1
    EXPECT_STREQ(useful_F::sek_to_uptime(34534).c_str(),"\n0 day 9 hours 35 minutes 34 seconds");
30
1
}
31
32
TEST(functions_, tokenizerEmpty)
33
1
{
34
1
     std::string test_msg = "";
35
1
     std::vector<std::string> test_v;
36
1
37
1
     EXPECT_EQ(test_v.size(), 0);
38
1
     EXPECT_THROW(useful_F::tokenizer(test_v,"= ",test_msg),std::string);
39
1
}
40
41
TEST(functions_, removeHtmlTag)
42
1
{
43
1
     std::string test_msg = "<html>test</html>";
44
1
     std::string test_pure_str = useful_F_libs::removeHtmlTag(test_msg);
45
1
46
1
     EXPECT_STREQ(test_pure_str.c_str(),"test");
47
1
}
48
49
TEST(functions_, repalceAll)
50
1
{
51
1
     std::string test_msg = "one two three";
52
1
     std::string test_pure_str = useful_F_libs::replaceAll(test_msg,"two","zero");
53
1
54
1
     EXPECT_STREQ(test_pure_str.c_str(),"one zero three");
55
1
}
56
57
TEST(functions_, split)
58
1
{
59
1
    std::string test_msg = "one two three";
60
1
    std::vector<std::string> test_v;
61
1
62
1
    EXPECT_EQ(test_v.size(), 0);
63
1
    test_v = useful_F::split(test_msg,' ');
64
1
65
1
    EXPECT_EQ(test_v.size(),3);
66
1
    EXPECT_STREQ(test_v.at(2).c_str(),"three");
67
1
}
68
69
TEST(functions_, RSHash)
70
1
{
71
1
    std::string msg = "test msg";
72
1
    std::string s1  = useful_F::RSHash(msg, 33, 44);
73
1
    std::string s2  = useful_F::RSHash(msg, 33 ,44);
74
1
    EXPECT_STREQ(s1.c_str(), s2.c_str());
75
1
76
1
    s1 = useful_F::RSHash(msg, 35, 44);
77
1
    s2 = useful_F::RSHash(msg, 33 ,44);
78
1
    EXPECT_STRNE(s1.c_str(), s2.c_str());
79
1
}
80
81
TEST_F(functions_fixture, setStaticData)
82
1
{
83
1
    test_my_data.sleeper = 99;
84
1
    EXPECT_EQ( useful_F::myStaticData->sleeper, 99 );
85
1
    thread_data test_my_data2;
86
1
    test_my_data2.sleeper = 88;
87
1
    EXPECT_EQ( test_my_data2.sleeper, 88 );
88
1
    EXPECT_EQ( useful_F::myStaticData->sleeper, 99 );
89
1
    useful_F::setStaticData(&test_my_data2);
90
1
    EXPECT_EQ( useful_F::myStaticData->sleeper, 88 );
91
1
}
92
93
TEST_F(functions_fixture, sleepThread)
94
1
{
95
1
    std::array <Thread_array_struc,10> test_THRARRSTR;
96
1
    test_my_data.main_THREAD_arr = &test_THRARRSTR;
97
1
98
1
    MPD_info test_ptr_MPD;
99
1
    test_ptr_MPD.volume = 3;
100
1
    test_my_data.ptr_MPD_info = &test_ptr_MPD;
101
1
102
1
   // RADIO_EQ_CONTAINER_STUB test_rec(&test_my_data);
103
1
    std::shared_ptr<RADIO_EQ_CONTAINER> test_rec = std::make_shared<RADIO_EQ_CONTAINER>(&test_my_data);
104
1
    test_rec->loadConfig(test_server_set.radio433MHzConfigFile);
105
1
    test_my_data.main_REC = (test_rec);
106
1
    test_my_data.alarmTime.time = Clock::getTime();
107
1
    test_my_data.alarmTime.state = STATE::ACTIVE;
108
1
109
1
    test_my_data.sleeper = 10;
110
1
111
1
    blockQueue test_q;
112
1
    test_q._clearAll();
113
1
    EXPECT_EQ(test_q._size(),0);
114
1
    useful_F::sleeper_mpd(&test_my_data,"test sleep");
115
1
    EXPECT_EQ(test_q._size(),1);
116
3
    EXPECT_EQ(test_q._get(), MPD_COMMAND::STOP) << "NIE ZATRZYMANO MUZYKI :(";
117
1
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/command_put.cpp
Line
Count
Source
1
#include "command_put.h"
2
#include "../../../src/CRON/cron.hpp"
3
4
command_put::command_put(const std::string &name):command(name)
5
8
{
6
8
}
7
8
std::string command_put::execute(std::vector<std::string> &v, thread_data *my_data)
9
1
{
10
1
    std::string str_buf = "command put - wrong paramiter: ";
11
1
    if (v.size() > 1){
12
1
        if (v[1] =="temperature")
13
1
        {
14
1
            str_buf.erase();
15
1
            my_data->main_iDomTools->send_temperature_thingSpeak();
16
1
            str_buf = "DONE";
17
1
        }
18
1
    }
19
1
    return str_buf;
20
1
}
21
22
std::string command_put::help()
23
1
{
24
1
    std::stringstream help;
25
1
    help << "put <parameter> - " << std::endl << std::endl;
26
1
    help << "parameter:" << std::endl;
27
1
    help << "\ttemperature - put actual temperature from inside and outside and smog on thingspeak\n" << std::endl;
28
1
    return help.str();
29
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/functions/tests/functions_stub.cpp
Line
Count
Source (jump to first uncovered line)
1
#include "../functions.h"
2
#include "test_data.h"
3
4
void useful_F::clearThreadArray(thread_data *my_data)
5
8
{
6
8
    std::cout << "useful_F::clearThreadArray(thread_data *my_data)" << std::endl;
7
8
}
8
9
10
11
int useful_F::runLinuxCommand(const std::string& cmd){
11
11
    std::cout << "runLinuxCommand(): " << cmd << std::endl;
12
11
    return TEST_DATA::runLinuxCommandReturn;
13
11
}
14
15
bool useful_F::go_while = true;
16
bool useful_F::workServer = true;
17
18
0
void useful_F::button_interrupt(){}
19
20
51
std::string useful_F::send_to_arduino(thread_data *my_data, const std::string& d){
21
51
    puts("useful_F::send_to_arduino()");
22
51
    return TEST_DATA::return_send_to_arduino;
23
51
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/command_show.cpp
Line
Count
Source
1
#include <strstream>
2
#include "command_show.h"
3
#include "../../../src/functions/functions.h"
4
5
command_show::command_show(const std::string &name):command(name)
6
16
{
7
16
8
16
}
9
10
std::string command_show::execute(std::vector<std::string> &v, thread_data *my_data)
11
9
{
12
9
    std::string str_buf = "show what?";
13
9
    if (v.size() > 1){
14
8
        if (v[1] =="log")
15
4
        {
16
4
            if (v.size() >2 && v.size() < 4){
17
1
                 return useful_F::l_send_file(_logfile,v[2],true);
18
1
            }
19
3
            else if (v.size() > 3){
20
2
                if (v[2] == "no"){
21
1
                 return useful_F::l_send_file(_logfile,v[3],false);
22
1
                }
23
1
                else{
24
1
                    return "do you mean : show log no <string>?";
25
1
                }
26
1
            }
27
1
            return useful_F::l_send_file(_logfile,"");
28
1
        }
29
4
        if (v[1]=="thread")
30
3
        {
31
3
            if (v.size() < 3){
32
1
                return "No ID";
33
1
            }
34
2
            else {
35
2
                if (v [2] !="all"){
36
1
                    std::stringstream ss;
37
1
                    ss << my_data->main_THREAD_arr->at(std::stoi(v[2])).thread_ID;
38
1
                    str_buf = my_data->main_THREAD_arr->at(std::stoi(v[2])).thread_name;
39
1
                    str_buf += "ID: ";
40
1
                    str_buf += ss.str();
41
1
                    str_buf += " socket: ";
42
1
                    str_buf += std::to_string(my_data->main_THREAD_arr->at(std::stoi(v[2])).thread_socket);
43
1
                    return str_buf;
44
1
                }
45
1
                else{
46
1
                    str_buf.erase();
47
1
                    std::stringstream ss;
48
11
                    for (int i =0; i< iDomConst::MAX_CONNECTION;++i)
49
10
                    {
50
10
                        ss.clear();
51
10
                        ss = std::stringstream();
52
10
                        str_buf += std::to_string(i)+" ";
53
10
                        str_buf += my_data->main_THREAD_arr->at(i).thread_name;
54
10
                        str_buf += "\t ID: ";
55
10
                        ss << my_data->main_THREAD_arr->at(i).thread_ID;
56
10
                        str_buf += ss.str();
57
10
                        int idSocket = my_data->main_THREAD_arr->at(i).thread_socket;
58
10
59
10
                        if (idSocket != 0 && idSocket != 1){
60
1
                            str_buf += " socket: ";
61
1
                            str_buf += std::to_string(my_data->main_THREAD_arr->at(i).thread_socket);
62
1
                        }
63
10
                        str_buf += "\n";
64
10
                    }
65
1
                    return str_buf;
66
1
                }
67
1
            }
68
1
        }
69
1
        else {
70
1
            return "wrong parameter: "+v[1];
71
1
        }
72
1
    }
73
1
    return str_buf;
74
1
}
75
76
std::string command_show::help()
77
1
{
78
1
    std::stringstream help;
79
1
    help << "show <parameter>- for show something" <<std::endl << std::endl;
80
1
    help << "parameter:" << std::endl;
81
1
    help << "\tlog             - show all server log" << std::endl;
82
1
    help << "\tlog <string>    - show all server log lines which contain <string>" << std::endl;
83
1
    help << "\tlog no <string> - show all server log lines which NO contain <string>" << std::endl;
84
1
    help << "\tthread all      - show all server thread pid " << std::endl;
85
1
    help << "\tthread <number> - show server <number> thread pid " << std::endl;
86
1
87
1
    return help.str();
88
1
}
89
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDom_server_OOP.h
Line
Count
Source
1
#ifndef GLOBAL_H
2
#define GLOBAL_H
3
4
#include <iostream>
5
#include <fstream>
6
#include <string>
7
#include <cstdlib>
8
#include <pthread.h>
9
#include <stdio.h>
10
#include <stdlib.h>
11
#include <sys/socket.h>
12
#include <sys/types.h>
13
#include <netinet/in.h>
14
#include <vector>
15
#include <thread>
16
#include <arpa/inet.h>
17
#include <netinet/in.h>
18
#include <unistd.h>
19
#include <sys/fcntl.h>
20
#include <unistd.h>
21
#include <errno.h>
22
#include <signal.h>
23
#include <time.h>
24
#include <wiringPi.h>
25
#include <chrono>
26
#include <array>
27
28
// MOJE BIBLIOTEKI
29
#include "KEY/key.h"
30
#include "logger/logger.hpp"
31
#include "files_tree/files_tree.h"
32
#include "menu_tree/menu_tree.h"
33
#include "LCD_c/lcd_c.h"
34
#include "command/command.h"
35
#include "../libs/event_counters/event_counters_handler.h"
36
#include "iDomTools/idomtools.h"
37
#include "iDomStatus/idomstatus.h"
38
#include "iDomSaveState/idom_save_state.h"
39
40
12
#define log_file_cout  f_log //std::cout zmien f_log na std::cout i bedzie wypisywac na ekran
41
6
#define log_file_mutex f_log
42
43
enum class iDomStateEnum{
44
    CLOSE = 0,
45
    RELOAD,
46
    ERROR,
47
    WORKING,
48
    HARD_RELOAD
49
};
50
51
namespace iDomConst
52
{
53
constexpr int MAX_CONNECTION = 10;
54
constexpr int FREE  = 1;
55
constexpr int RS232 = 11;
56
constexpr int CLOCK = 12;
57
constexpr int ok    = 0;
58
constexpr int GPIO_SPIK = 21;
59
constexpr int GPIO_PRINTER = 22;
60
constexpr int BUTTON_PIN = 25;
61
}
62
struct ALERT
63
{
64
    Clock time;
65
    STATE state = STATE::DEACTIVE;
66
    unsigned int fromVolume = 48;
67
    unsigned int toVolume = 58;
68
    unsigned int radioID = 8;
69
};
70
71
extern std::string _logfile;
72
extern Logger log_file_mutex;
73
extern std::string buffer;
74
75
enum class TEMPERATURE_STATE;
76
enum class PILOT_KEY;
77
78
struct MPD_info{
79
    std::string title   = "NULL";
80
    std::string radio   = "NULL";
81
    std::string artist  = "NULL";
82
    int volume = 0;
83
    bool isPlay = false;
84
    int currentSongID = 0;
85
    std::vector <std::string> songList = {"NULL"};
86
};
87
struct s_pointer{
88
    unsigned int *ptr_who;
89
    int32_t *ptr_buf;
90
};
91
92
struct Thread_array_struc {
93
    std::thread thread;
94
    std::thread::id thread_ID = std::thread::id(0);
95
    std::string thread_name;
96
    int thread_socket = 0;
97
};
98
99
struct address_another_servers {
100
    int id;
101
    std::string SERVER_IP;
102
};
103
104
struct FTP_SERVER{
105
    std::string URL;
106
    std::string user;
107
    std::string pass;
108
};
109
struct iDOM_STATE{
110
    STATE houseState = STATE::UNDEFINE;
111
112
};
113
114
struct config{
115
    std::string portRS232;
116
    std::string portRS232_clock;
117
    std::string BaudRate;
118
    std::string RFLinkPort;
119
    std::string RFLinkBaudRate;
120
    int PORT;
121
    std::string SERVER_IP;
122
    std::string MPD_IP;
123
    std::string MOVIES_DB_PATH;
124
    std::string MENU_PATH;
125
    std::string THREAD_MPD   = "NULL";
126
    std::string THREAD_IRDA  = "NULL";
127
    std::string THREAD_CRON  = "NULL";
128
    std::string THREAD_RS232 = "NULL";
129
    std::string THREAD_DUMMY = "NULL";
130
    std::string TS_KEY= " gg ";
131
    std::string cameraLedON = "";
132
    std::string cameraLedOFF ="";
133
    std::string cameraURL="";
134
    std::string facebookAccessToken = "";
135
    std::string viberToken = "NULL";
136
    std::string viberAvatar;
137
    std::vector <std::string> viberReceiver;
138
    std::string viberSender;
139
    std::string radio433MHzConfigFile;
140
    std::string omxplayerFile = "NULL";
141
    int ID_server = 0;
142
    int v_delay;
143
    bool encrypted = true;
144
145
    FTP_SERVER ftpServer;
146
    std::string lightningApiURL = "NULL";
147
    std::string saveFilePath = "NULL";
148
};
149
150
struct LED_Strip{
151
    std::string from;
152
    std::string to;
153
    std::string R;
154
    std::string G;
155
    std::string B;
156
    std::string colorName;
157
158
    LED_Strip (int from, int to, int r, int g, int b, std::string colorName = "NULL"):from(std::to_string(from)),
159
        to(std::to_string(to)),
160
        R(std::to_string(r)),
161
        G(std::to_string(g)),
162
        B(std::to_string(b)),
163
        colorName(colorName)
164
    {
165
166
    }
167
    LED_Strip (const std::string& from,
168
               const std::string& to,
169
               const std::string& r,
170
               const std::string& g,
171
               const std::string& b,
172
               const std::string& colorName = "NULL"):
173
        from(from),
174
        to(to),
175
        R(r),
176
        G(g),
177
        B(b),
178
        colorName(colorName)
179
    {
180
181
    }
182
183
    void set (const std::string& from,
184
              const std::string& to,
185
              const std::string& r,
186
              const std::string& g,
187
              const std::string& b,
188
              const std::string& colorName = "NULL")
189
    {
190
        this->from =from;
191
        this->to = to;
192
        R = r;
193
        G = g;
194
        B = b;
195
        this->colorName =colorName;
196
    }
197
198
    void set (int from, int to, int r, int g, int b, std::string colorName = "NULL"){
199
        this->from = std::to_string(from);
200
        this->to = std::to_string(to);
201
        R = std::to_string(r);
202
        G = std::to_string(g);
203
        B = std::to_string(b);
204
        this->colorName =colorName;
205
    }
206
207
    std::string getColorName() const{
208
        return colorName;
209
    }
210
211
    std::string get(unsigned int _from, unsigned int _to) const{
212
        if (_from != 0 || _to != 60){
213
            return "LED:["+std::to_string(_from)+"-"+std::to_string(_to)+"-"+R+"-"+G+"-"+B+"];";
214
        }
215
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
216
    }
217
218
    std::string makeCommand(const std::string& from,
219
                            const std::string& to,
220
                            const std::string& R,
221
                            const std::string& G,
222
                            const std::string& B){
223
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
224
    }
225
};
226
227
struct pilot_led{
228
    unsigned int counter=0;
229
    std::vector<LED_Strip> colorLED   = { LED_Strip(1,60,237,145,33 ,"carrot orange"),
230
                                          LED_Strip(1,60,255,0,0    ,"red"),
231
                                          LED_Strip(1,60,0,255,0    ,"green"),
232
                                          LED_Strip(1,60,0,0,255    ,"blue"),
233
                                          LED_Strip(1,60,255,255,255,"white"),
234
                                          LED_Strip(1,60,255,255,0  ,"yellow"),
235
                                          LED_Strip(1,60,0,255,255  ,"cyan"),
236
                                          LED_Strip(1,60,255,0,255  ,"magenta")
237
                                        };
238
};
239
240
class command; // for struc thread_data req
241
class iDomTOOLS;
242
class RADIO_EQ_CONTAINER;
243
class RFLinkHandler;
244
245
struct thread_data{
246
    int s_client_sock;
247
    struct sockaddr_in from;
248
    struct config *server_settings = NULL;
249
    struct s_pointer pointer;
250
    LCD_c *mainLCD = NULL;
251
    files_tree *main_tree = NULL;
252
    menu_tree *main_MENU = NULL;
253
    iDomTOOLS *main_iDomTools = NULL;
254
    RFLinkHandler *main_RFLink = NULL;
255
    std::array<Thread_array_struc, iDomConst::MAX_CONNECTION> *main_THREAD_arr = NULL;
256
    time_t start;
257
    time_t now_time;
258
    int sleeper;
259
    std::map <std::string, std::unique_ptr <KEY> > key_map;
260
    MPD_info *ptr_MPD_info = NULL;
261
    pilot_led * ptr_pilot_led = NULL;
262
    std::map <std::string, std::unique_ptr<command> >* commandMapPtr = NULL;
263
    event_counters_handler myEventHandler;
264
    std::string encriptionKey = "40%";
265
    iDomSTATUS *main_iDomStatus;
266
    iDOM_STATE idom_all_state;
267
    ALERT alarmTime;
268
    std::shared_ptr<RADIO_EQ_CONTAINER> main_REC;
269
    iDomStateEnum iDomProgramState = iDomStateEnum::WORKING;
270
};
271
272
struct thread_data_rs232{
273
    std::string portRS232;
274
    std::string portRS232_clock;
275
    std::string BaudRate;
276
    struct s_pointer pointer;
277
};
278
279
#endif // GLOBAL_H
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/command_sleep.cpp
Line
Count
Source
1
#include "command_sleep.h"
2
#include "../../functions/functions.h"
3
#include "../../thread_functions/iDom_thread.h"
4
5
command_sleep::command_sleep(const std::string &name):command(name)
6
12
{
7
12
}
8
9
std::string command_sleep::execute(std::vector<std::string> &v, thread_data *my_data)
10
5
{   if (v.size()== 1)
11
1
    {
12
1
        return "sleep set to: "+ std::to_string(my_data->sleeper);
13
1
    }
14
4
    else if (v.size() == 3 ){
15
3
        if (v[1] == "set"){
16
2
            int sleep = 0;
17
2
            try {
18
2
                sleep = std::stoi(v[2]);
19
2
            }
20
2
            catch (...){
21
1
                return "system need intiger > 0 not: " +v[2];
22
1
            }
23
1
24
1
            my_data->sleeper = sleep;
25
1
26
1
            return iDOM_THREAD::start_thread("Sleep MPD",useful_F::sleeper_mpd,my_data);
27
1
        }
28
1
        else {
29
1
            return "wrong parametr "+v[1];
30
1
        }
31
1
    }
32
1
    return "internal error";
33
1
}
34
35
std::string command_sleep::help()
36
1
{
37
1
    std::stringstream help;
38
1
    help << "sleep - show actual time to stop play music" << std::endl;
39
1
    help << "sleep set <int> - start sleep for <int> minutes" << std::endl;
40
1
41
1
    return help.str();
42
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/logger/logger.hpp
Line
Count
Source
1
/*
2
 * logger.hpp
3
 *
4
 *
5
 * Logger Library Header
6
 *
7
 *
8
 * Copyright (C) 2013-2014  Bryant Moscon - bmoscon@gmail.com
9
 *
10
 * Permission is hereby granted, free of charge, to any person obtaining a copy
11
 * of this software and associated documentation files (the "Software"), to
12
 * deal in the Software without restriction, including without limitation the
13
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
14
 * sell copies of the Software, and to permit persons to whom the Software is
15
 * furnished to do so, subject to the following conditions:
16
 *
17
 * 1. Redistributions of source code must retain the above copyright notice,
18
 *    this list of conditions, and the following disclaimer.
19
 *
20
 * 2. Redistributions in binary form must reproduce the above copyright notice,
21
 *    this list of conditions and the following disclaimer in the documentation
22
 *    and/or other materials provided with the distribution, and in the same
23
 *    place and form as other copyright, license and disclaimer information.
24
 *
25
 * 3. The end-user documentation included with the redistribution, if any, must
26
 *    include the following acknowledgment: "This product includes software
27
 *    developed by Bryant Moscon (http://www.bryantmoscon.org/)", in the same
28
 *    place and form as other third-party acknowledgments. Alternately, this
29
 *    acknowledgment may appear in the software itself, in the same form and
30
 *    location as other such third-party acknowledgments.
31
 *
32
 * 4. Except as contained in this notice, the name of the author, Bryant Moscon,
33
 *    shall not be used in advertising or otherwise to promote the sale, use or
34
 *    other dealings in this Software without prior written authorization from
35
 *    the author.
36
 *
37
 *
38
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
41
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
42
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
44
 * THE SOFTWARE.
45
 *
46
 */
47
#ifndef __LOGGER__
48
#define __LOGGER__
49
50
#include <fstream>
51
#include <cassert>
52
#include <ctime>
53
#include <sstream>
54
55
// Log levels
56
typedef enum {
57
    US =0,
58
    VERBOSE,
59
    DEBUG,
60
    INFO,
61
    WARNING,
62
    ERROR,
63
    CRITICAL,
64
    FATAL
65
} logger_level;
66
67
class Logger : public std::ostringstream {
68
public:
69
70
    explicit Logger(const char *f);
71
    explicit Logger(const std::string& f);
72
    Logger (const Logger &);
73
    Logger &operator= (const Logger &);
74
    ~Logger();
75
    static pthread_mutex_t mutex_log;
76
77
    void set_level(const logger_level& level);
78
    void flush();
79
    void mutex_lock();
80
    void mutex_unlock();
81
82
    template <typename T>
83
    Logger& operator<<(const T& t)
84
2
    {
85
2
        *static_cast<std::ostringstream *>(this) << t;
86
2
        return (*this);
87
2
    }
88
89
    Logger& operator<<(const logger_level& level);
90
    typedef Logger& (* LoggerManip)(Logger&);
91
    Logger& operator<<(LoggerManip m);
92
93
private:
94
    std::string get_time() const;
95
    inline const char* level_str(const logger_level& level);
96
public:
97
    std::ofstream _file;
98
private:
99
    std::ostream& _log;
100
    logger_level _level;
101
    logger_level _line_level;
102
};
103
104
105
namespace std { 
106
inline Logger& endl(Logger& out)
107
{
108
    out.put('\n');
109
    out.flush();
110
    return (out);
111
}
112
}// end namespace std
113
114
#endif
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/command_state.cpp
Line
Count
Source
1
#include "command_state.h"
2
3
command_state::command_state(const std::string &name):command(name)
4
10
{
5
10
}
6
7
std::string command_state::execute(std::vector<std::string> &v, thread_data *my_data)
8
3
{
9
3
    std::string ret = "need parameter!\n" + help();
10
3
    if (v.size() > 1)
11
2
    {
12
2
13
2
        if (v[1] == "all")
14
1
        {
15
1
            return my_data->main_iDomStatus->getAllObjectsStateString();
16
1
        }
17
1
        if (v[1] != "all")
18
1
        {
19
1
            return my_data->main_iDomStatus->getObjectStateString(v[1]);
20
1
        }
21
1
22
1
    }
23
1
    return ret;
24
1
}
25
26
std::string command_state::help()
27
4
{
28
4
    std::stringstream help;
29
4
    help << "state all/<name> - show state" << std::endl;
30
4
    return help.str();
31
4
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDomSaveState/idom_save_state.cpp
Line
Count
Source
1
#include <iostream>     // std::cout
2
#include <fstream>
3
#include "idom_save_state.h"
4
#include "../iDom_server_OOP.h"
5
6
iDom_SAVE_STATE::iDom_SAVE_STATE(const std::string &path): m_path(path)
7
50
{
8
50
#ifdef BT_TEST
9
50
    puts("iDom_SAVE_STATE::iDom_SAVE_STATE()");
10
50
#endif
11
50
}
12
13
iDom_SAVE_STATE::~iDom_SAVE_STATE()
14
50
{
15
50
#ifdef BT_TEST
16
50
    puts("iDom_SAVE_STATE::~iDom_SAVE_STATE()");
17
50
#endif
18
50
}
19
20
nlohmann::json iDom_SAVE_STATE::read()
21
3
{
22
3
    std::lock_guard<std::mutex> lGuard(m_mutex);
23
3
    // read a JSON file
24
3
    std::ifstream i(m_path);
25
3
    nlohmann::json j;
26
3
    i >> j;
27
3
28
3
    log_file_mutex.mutex_lock();
29
3
    log_file_cout << INFO << "czytam zapisany stan parametrow iDom" << std::endl;
30
3
    log_file_mutex.mutex_unlock();
31
3
32
3
    return j;
33
3
}
34
35
void iDom_SAVE_STATE::write(const nlohmann::json &jj)
36
48
{
37
48
    std::lock_guard<std::mutex> lGuard(m_mutex);
38
48
    // write prettified JSON to another file
39
48
    std::ofstream o(m_path);
40
48
    o << std::setw(4) << jj << std::endl;
41
48
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/command_uptime.cpp
Line
Count
Source
1
#include "command_uptime.h"
2
#include "../../../src/functions/functions.h"
3
4
command_UPTIME::command_UPTIME(const std::string &name):command(name)
5
8
{
6
8
7
8
}
8
9
std::string command_UPTIME::execute(std::vector<std::string> &v, thread_data *my_data)
10
1
{
11
1
    std::string str_buf;
12
1
    time(&my_data->now_time);
13
1
    str_buf ="uptime: ";
14
1
    str_buf.append(useful_F::sek_to_uptime(difftime(my_data->now_time,my_data->start) ) );
15
1
    return str_buf;
16
1
}
17
18
std::string command_UPTIME::help()
19
1
{
20
1
    std::stringstream help;
21
1
    help << "uptime - show server uptime" << std::endl;
22
1
    return help.str();
23
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDomSaveState/test/iDomSaveState_BT.cpp
Line
Count
Source
1
#include <gtest/gtest.h>
2
3
#include "test_data.h"
4
#include "../idom_save_state.h"
5
#include "json.hpp"
6
7
TEST(iDomSaveState, write_and_read)
8
1
{
9
1
    iDom_SAVE_STATE test_saveState("/mnt/ramdisk/iDomStateTest.save");
10
1
    nlohmann::json test_json ;
11
1
12
1
    test_json["happy"] = true;
13
1
    test_json["pi"] = 3.14;
14
1
15
1
    nlohmann::json test_json_in_json;
16
1
    test_json_in_json["name"] = "cyniu";
17
1
    test_json_in_json["age"] = 30;
18
1
19
1
    test_json["person"] = test_json_in_json;
20
1
21
1
    test_saveState.write(test_json);
22
1
    nlohmann::json test_json2 = test_saveState.read();
23
3
    EXPECT_DOUBLE_EQ(test_json.at("pi").get<double>(),
24
3
                     test_json2.at("pi").get<double>()) << "wartosci pi nie sa rowne";
25
1
26
3
    EXPECT_TRUE(test_json2.at("happy").get<bool>()) << " nie jest happy";
27
1
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/commandexit.cpp
Line
Count
Source
1
#include "commandexit.h"
2
3
commandEXIT::commandEXIT(const std::string &name):command(name)
4
8
{
5
8
}
6
7
std::string commandEXIT::execute(std::vector<std::string> &v, thread_data *my_data)
8
1
{
9
1
    return "\nEND.\n";
10
1
}
11
12
std::string commandEXIT::help()
13
1
{
14
1
    return "exit - disconnect from server\n";
15
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDomStatus/idomstatus.cpp
Line
Count
Source
1
#include "idomstatus.h"
2
3
iDomSTATUS::iDomSTATUS()
4
198
{
5
198
}
6
7
void iDomSTATUS::addObject(std::string name, STATE st)
8
1.17k
{
9
1.17k
    std::lock_guard < std::mutex > lock ( m_lockGuard);
10
1.17k
    m_stateMAP.insert(std::make_pair(name,st));
11
1.17k
}
12
13
void iDomSTATUS::setObjectState(const std::string& name, STATE st)
14
107
{
15
107
    std::lock_guard < std::mutex > lock ( m_lockGuard);
16
107
    auto i = m_stateMAP.find(name);
17
107
    if (i != m_stateMAP.end()){
18
82
        i->second = st;
19
82
    }
20
107
    else
21
107
    {
22
25
        lock.~lock_guard();
23
25
        addObject(name,st);
24
25
    }
25
107
}
26
27
STATE iDomSTATUS::getObjectState(const std::string& name)
28
77
{
29
77
    std::lock_guard < std::mutex > lock ( m_lockGuard);
30
77
    auto i = m_stateMAP.find(name);
31
77
    if (i != m_stateMAP.end())
32
77
    {
33
69
        return i->second;
34
69
    }
35
77
    return STATE::UNKNOWN;
36
77
}
37
38
std::string iDomSTATUS::getObjectStateString(const std::string& name)
39
144
{
40
144
    std::lock_guard < std::mutex > lock ( m_lockGuard);
41
144
    auto i = m_stateMAP.find(name);
42
144
    if (i != m_stateMAP.end())
43
144
    {
44
105
        return stateToString( i->second);
45
105
    }
46
144
    return stateToString(STATE::UNKNOWN) + " "+name;
47
144
}
48
49
std::string iDomSTATUS::getAllObjectsStateString()
50
3
{
51
3
    std::stringstream st;
52
3
    st << "state: ";
53
3
    std::lock_guard < std::mutex > lock( m_lockGuard);
54
3
    for (auto elm : m_stateMAP)
55
20
    {
56
20
        st << elm.first << "=";
57
20
        st << stateToString(elm.second) << " ";
58
20
    }
59
3
    return st.str();
60
3
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/commandrs232.cpp
Line
Count
Source
1
#include "commandrs232.h"
2
#include "../../../src/functions/functions.h"
3
4
commandRS232::commandRS232(const std::string &name):command(name)
5
15
{
6
15
}
7
std::string commandRS232::execute(std::vector<std::string> &v, thread_data *my_data)
8
8
{
9
8
    std::string str_buf ="default";
10
8
11
8
    if (v[1]=="get")
12
2
    {
13
2
        if (v[2]=="temperature")
14
1
        {
15
1
            str_buf = useful_F::send_to_arduino(my_data,"temperature:339;");
16
1
            str_buf += std::to_string(++counter);
17
1
        }
18
1
        else
19
1
        {
20
1
            str_buf = ("wrong parameter: "+v[2]);
21
1
        }
22
2
    }
23
6
24
6
    else if (v[1]=="send")
25
1
    {
26
1
        str_buf = useful_F::send_to_arduino(my_data,v[2]);
27
1
    }
28
5
    else if (v[1]=="error")
29
4
    {
30
4
        if (v.size() < 3 )
31
1
            return "add more parameter to error";
32
3
        std::string msg;
33
10
        for (unsigned int i = 2; i < v.size(); ++i)
34
7
        {
35
7
            msg+=" ";
36
7
            msg+=v[i];
37
7
        }
38
3
        if(v[2]=="Temperature" && v[3]=="error")
39
1
        {
40
1
41
1
            my_data->myEventHandler.run("RS232")->addEvent("RS232 error event: "+msg);
42
1
            log_file_mutex.mutex_lock();
43
1
            log_file_cout << WARNING<< "RS232 ERROR event: " << msg << std::endl;
44
1
            log_file_mutex.mutex_unlock();
45
1
        }
46
2
        else if (v[2]=="test" && v[3]=="msg")
47
1
        {
48
1
            log_file_mutex.mutex_lock();
49
1
            log_file_cout << DEBUG << "RS232 ERROR debug : "<<msg << std::endl;
50
1
            log_file_mutex.mutex_unlock();
51
1
            str_buf = "DONE!";
52
1
        }
53
1
        else
54
1
        {
55
1
            log_file_mutex.mutex_lock();
56
1
            log_file_cout << CRITICAL << "RS232 ERROR unknown : "<<msg << std::endl;
57
1
            log_file_mutex.mutex_unlock();
58
1
        }
59
3
    }
60
1
    else
61
1
    {
62
1
        str_buf = ("wrong parameter: "+v[1]);
63
1
    }
64
8
    return str_buf;
65
8
}
66
67
std::string commandRS232::help()
68
1
{
69
1
    std::stringstream help;
70
1
    help << "RS232 - communication with Arduino:" << std::endl;
71
1
    help << "parameter:" << std::endl << std::endl;
72
1
    help << "\tsend <command> - send <command> to Arduino" << std::endl;
73
1
    help << "\tget <param> - get <param> from Arduino" << std::endl;
74
1
    help << "\t\ttemperature - get temeprature INSIDE + OUTSIDE" << std::endl;
75
1
76
1
    return help.str();
77
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/libs/Statistic/statistic.h
Line
Count
Source (jump to first uncovered line)
1
#ifndef STATISTIC_H
2
#define STATISTIC_H
3
#include <iostream>
4
#include <deque>
5
#include <numeric>
6
#include <algorithm>
7
#include <sstream>
8
#include <cmath>
9
#include <vector>
10
11
template <class T>
12
class STATISTIC
13
{
14
public:
15
    STATISTIC(unsigned int size): m_size(size)
16
16
    {
17
16
18
16
    }
19
    void resize(unsigned int i){
20
        if (i < m_size){
21
            while(m_dequeue.size()> i){
22
                pop_front();
23
            }
24
        }
25
        m_size = i;
26
    }
27
    T size(){
28
        return  static_cast<T>(m_dequeue.size());
29
    }
30
    void push_front(T v){
31
        if (m_dequeue.size() >= m_size){
32
            pop_back();
33
        }
34
        m_dequeue.push_front(v);
35
    }
36
292
    void push_back(T v){
37
292
        if (m_dequeue.size() >= m_size){
38
0
            pop_front();
39
0
        }
40
292
        m_dequeue.push_back(v);
41
292
    }
42
    void pop_back(){
43
        m_dequeue.pop_back();
44
        // std::cout <<"pop_back"<<std::endl;
45
    }
46
0
    void pop_front(){
47
0
        m_dequeue.pop_front();
48
0
        // std::cout <<"pop_front"<<std::endl;
49
0
    }
50
    ///////////////////////////////////////////// statistic /////////////////////////////
51
8
    T median(){
52
8
        auto backup = m_dequeue;
53
8
        std::sort(backup.begin(), backup.end());
54
8
        if (backup.size() % 2 != 0){
55
2
            return backup[backup.size() / 2];
56
2
        }
57
8
        else{
58
6
            T m = backup[backup.size() / 2] + backup[(backup.size() / 2)-1];
59
6
            return m /2;
60
6
        }
61
8
    }
62
    T sum(){
63
        return std::accumulate(m_dequeue.begin(), m_dequeue.end(), static_cast<T>(0));
64
    }
65
66
    T average(){
67
        T av  = sum() /size();
68
        return av;
69
    }
70
71
    T max(){
72
        T max = m_dequeue[0];
73
        for (auto v : m_dequeue){
74
            if (v > max){
75
                max = v;
76
            }
77
        }
78
        return max;
79
    }
80
81
    T min(){
82
        T min = m_dequeue[0];
83
        for (auto v : m_dequeue){
84
            if (v < min){
85
                min = v;
86
            }
87
        }
88
        return min;
89
    }
90
91
    T range(){
92
        return max() - min();
93
    }
94
95
    T standardDeviation(){
96
        double standardDeviation = 0.0;
97
        T _av = average();
98
99
        for(int i = 0; i < size(); ++i){
100
            standardDeviation += pow(m_dequeue.at(i) - _av, 2);
101
        }
102
        return sqrt(standardDeviation / size());
103
    }
104
105
    T coefficientOfVariation(){
106
107
        return (standardDeviation()/average()) /** 100*/;
108
    }
109
110
8
    T mode(){
111
8
112
8
        T _mode = 0;
113
8
        T _modeTemp = 0;
114
8
        int counter = 1;
115
8
        int modeCounter = 1;
116
8
        auto backup = m_dequeue;
117
8
        if(m_dequeue.size() == 1)
118
8
        {
119
2
            return m_dequeue.at(0);
120
2
        }
121
8
        std::sort(backup.begin(), backup.end());
122
6
#ifdef BT_TEST
123
6
        std::cout << " " << std::endl;
124
6
        for (auto i : backup)
125
144
        {
126
144
            std::cout << i << " ";
127
144
        }
128
6
        std::cout << " " << std::endl;
129
6
#endif
130
6
        _mode = _modeTemp = backup.at(0);
131
6
        backup.pop_front();
132
6
        for (auto b : backup)
133
138
        {
134
138
            if (_modeTemp == b)
135
138
            {
136
120
                modeCounter++;
137
120
            }
138
138
            else
139
138
            {
140
18
                _modeTemp = b;
141
18
                modeCounter = 1;
142
18
            }
143
138
144
138
            if(counter < modeCounter)
145
138
            {
146
72
                counter = modeCounter;
147
72
                _mode = _modeTemp;
148
72
            }
149
138
        }
150
6
#ifdef BT_TEST
151
6
        std::cout << " moda: " << _mode << " wystepuje razy " << counter << std::endl;
152
6
#endif
153
6
        return _mode;
154
8
    }
155
156
    float trend(){
157
        int down = 0;
158
        int eq = 0;
159
        int up = 0;
160
        int lp = 0;
161
        T diff = 0;
162
        T first = m_dequeue[0];
163
164
        for (auto i = 1; i < m_dequeue.size(); ++i){
165
            if (first < m_dequeue[i]){
166
                up++;
167
                if (m_dequeue[i] - first > diff){
168
                    diff = m_dequeue[i] - first;
169
                    lp = i;
170
                }
171
            }
172
            if (first == m_dequeue[i]){ eq++;}
173
            if (first > m_dequeue[i]){
174
                if (diff < first - m_dequeue[i] ){
175
                    diff = first - m_dequeue[i];
176
                    lp = i;
177
                }
178
                down++;
179
            }
180
            first = m_dequeue[i];
181
        }
182
        std::cout <<"up "<<up<<" eq "<< eq << " down "<< down <<" max diff "<< diff<<" lp "<<lp << std::endl;
183
        return 2.2;
184
    }
185
186
    bool isMoreDiff(T diff){
187
        if (m_dequeue.size()>2){
188
            T d = m_dequeue.at( m_dequeue.size()-2)
189
                    - m_dequeue.at( m_dequeue.size() - 1);
190
            d = fabs(d);
191
            if (d > diff && m_alarm == false){
192
                m_alarm = true;
193
                return true;
194
            }
195
            if (d <= diff){
196
                m_alarm = false;
197
                return false;
198
            }
199
        }
200
        return false;
201
    }
202
    std::pair<double,double> getLast2(){
203
        if (m_dequeue.size()>2){
204
            return std::make_pair(static_cast<double>(m_dequeue.at( m_dequeue.size()-2)),
205
                                  static_cast<double>(m_dequeue.at( m_dequeue.size()-1))    );
206
        }
207
#ifdef BT_TEST
208
        puts("no data - return 0.0 0.0");
209
#endif
210
        return std::make_pair(0.0,0.0);
211
    }
212
213
    /////////////////////////////////////////////////////////////////////////////////////
214
    void print(){
215
        for(auto n : m_dequeue){
216
            std::cout << ","<< n;
217
        }
218
        std::cout << " " <<std::endl;
219
    }
220
221
222
    std::string stats(){
223
224
        std::stringstream ss(" brak danych =(");
225
        if(size()>0)
226
        {
227
            ss.str("");
228
            ss <<"rozmiar tablicy: "<< size() <<std::endl
229
              << "min: "<< min() <<std::endl
230
              << "max: "<< max()<<std::endl
231
              << "srednia " << average() <<std::endl
232
              << "mediana " << median()  <<std::endl
233
              << "odchylenie st "<< standardDeviation() << std::endl
234
              << "wspolczynnik zmiennosci " << coefficientOfVariation() <<"%"<< std::endl
235
              << "Dominanta " << mode();
236
237
238
            ss << std::endl
239
               << "data " <<  std::endl;
240
            for(auto n : m_dequeue){
241
                ss << "|"<< n;
242
            }
243
        }
244
        ss <<  std::endl;
245
        return ss.str();
246
    }
247
248
private:
249
    unsigned int m_size;
250
    std::deque <T> m_dequeue;
251
    bool m_alarm = false;
252
};
253
254
#endif // STATISTIC_H
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandClass/commandtest.cpp
Line
Count
Source
1
#include "commandtest.h"
2
#include "../../functions/functions.h"
3
#include "../../../ftplibpp/ftplib.h"
4
5
commandTEST::commandTEST(const std::string &name):command(name)
6
10
{
7
10
}
8
9
std::string commandTEST::execute(std::vector<std::string> &v, thread_data *my_data)
10
3
{
11
3
12
3
    if (v[1] == "test")
13
1
    {
14
1
        std::string msg = "test - for test";
15
1
        my_data->main_iDomTools->runOnSunrise();
16
1
        return msg;
17
1
    }
18
2
    else if (v[1] == "throw")
19
1
    {
20
1
        throw std::string("test throw");
21
1
    }
22
1
    return help();
23
1
}
24
std::string commandTEST::help()
25
2
{
26
2
    std::stringstream help;
27
2
    help << "test - for test" << std::endl;
28
2
    help << "throw - trow test reload program" << std::endl;
29
2
    return help.str();
30
2
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/libs/useful/useful.h
Line
Count
Source
1
#ifndef Iusefull_H
2
#define Iusefull_H
3
4
#include <iostream>
5
#include <string>
6
#include <vector>
7
#include <ostream>
8
#include <chrono>
9
#include <sstream>
10
#include <stdio.h>
11
#include <stdlib.h>
12
#include <iomanip>
13
#ifndef ANDROID
14
#include "json.hpp"
15
#endif
16
17
std::vector<std::string> split_string(const std::string& s, char separator );
18
19
class useful_F_libs {
20
public:
21
    static  void write_to_mkfifo(const std::string& path, const std::string &msg);
22
    static  std::string read_from_mkfifo(const std::string &path);
23
    static size_t  WriteCallback(void *contents, size_t size, size_t nmemb, void *userp);
24
    static std::string find_tag (const std::string &temp);
25
    //////////////////// HTTP req //////////////////////////
26
    static std::string httpPost(const std::string &url, int timeoutSeconds);
27
    static std::string httpPost(const std::string &url);
28
    static void downloadFile(const std::string &url, const std::string &path, int timeoutSeconds);
29
    static std::string replaceAll(std::string str, const std::string& from, const std::string& to);
30
    static std::string removeHtmlTag(std::string &data);
31
    /////////////////////  JSON ////////////////////////////
32
33
#ifndef ANDROID
34
    static nlohmann::json getJson(const std::string &url);
35
#endif
36
};
37
namespace std
38
{
39
40
#ifdef ANDROID
41
template <typename T>
42
int stoi(T s){
43
    return atoi(s.c_str());
44
}
45
#endif
46
47
template <typename T>
48
std::string to_string(T value)
49
{
50
    std::ostringstream os;
51
    os << value;
52
    return os.str();
53
}
54
} // namespace std
55
56
template <typename T>
57
std::string to_string_with_precision(const T a_value, const int n = 4)
58
19
{
59
19
    std::ostringstream out;
60
19
    out << std::setprecision(n) << a_value;
61
19
    return out.str();
62
19
}
63
64
struct Clock{
65
private:
66
    std::time_t m_time;
67
#ifdef BT_TEST
68
    static unsigned int m_BT_H;
69
    static unsigned int m_BT_M;
70
#endif
71
public:
72
    unsigned int m_h = 0;
73
    unsigned int m_min = 0;
74
    Clock () {}
75
    Clock(std::string t){
76
        std::vector<std::string> vt = split_string(t,':');
77
        int h = std::stoi(vt.at(0));
78
        int m = std::stoi(vt.at(1));
79
        set(static_cast <unsigned int>(h),static_cast <unsigned int>(m));
80
    }
81
82
    Clock(unsigned int h, unsigned int m) {
83
        set(h,m);
84
    }
85
    /////////////////////////////////////////////////////////////////////////////////////
86
    void set(unsigned int h, unsigned int m){
87
        if (h<24 && m <60){
88
            this->m_h = h;
89
            this->m_min = m;
90
        }
91
        else {
92
            throw 0;
93
        }
94
    }
95
96
    /////////////////////////////////////////////////////////////////////////////////////
97
    const std::string getString(){
98
        std::stringstream ret;
99
        if (m_h < 10) {
100
            ret << "0";
101
        }
102
        ret << m_h;
103
        ret << ":";
104
        if (m_min < 10) {
105
            ret << "0";
106
        }
107
        ret << m_min;
108
        return ret.str();
109
    }
110
    /////////////////////////////////////////////////////////////////////////////////////
111
    bool operator == (const Clock & c){
112
        if ((this->m_h == c.m_h) && (this->m_min == c.m_min)){
113
            return true;
114
        }
115
        else{
116
            return false;
117
        }
118
    }
119
    /////////////////////////////////////////////////////////////////////////////////////
120
    bool operator != (const Clock & c){
121
        if ((this->m_h != c.m_h) || (this->m_min != c.m_min)){
122
            return true;
123
        }
124
        else{
125
            return false;
126
        }
127
    }
128
    /////////////////////////////////////////////////////////////////////////////////////
129
    friend std::ostream & operator<< (std::ostream &w ,  Clock &c) {
130
        return w << c.getString();
131
    }
132
    /////////////////////////////////////////////////////////////////////////////////////
133
    bool operator < (const Clock& c){
134
        if (this->m_h < c.m_h){
135
            return true;
136
        }
137
        else{
138
            if (this->m_h == c.m_h && this->m_min < c.m_min){
139
                return true;
140
            }
141
        }
142
        return false;
143
    }
144
    /////////////////////////////////////////////////////////////////////////////////////
145
    bool operator > (const Clock& c){
146
        if (this->m_h > c.m_h){
147
            return true;
148
        }
149
        else{
150
            if (this->m_h == c.m_h && this->m_min > c.m_min){
151
                return true;
152
            }
153
        }
154
        return false;
155
    }
156
    /////////////////////////////////////////////////////////////////////////////////////
157
    bool operator >= (const Clock& c){
158
        if (this->m_h > c.m_h){
159
            return true;
160
        }
161
        else if (this->m_h == c.m_h){
162
163
            if (this->m_min >= c.m_min){
164
                return true;
165
            }
166
        }
167
        return false;
168
    }
169
    /////////////////////////////////////////////////////////////////////////////////////
170
    bool operator <= (const Clock& c){
171
        if (this->m_h < c.m_h){
172
            return true;
173
        }
174
        else if (this->m_h == c.m_h){
175
176
            if (this->m_min <= c.m_min){
177
                return true;
178
            }
179
        }
180
        return false;
181
    }
182
    /////////////////////////////////////////////////////////////////////////////////////
183
    Clock  operator + (const Clock& c){
184
        unsigned int minutes, hours;
185
        minutes = m_min+ c.m_min;
186
        hours = m_h + c.m_h;
187
        if (minutes >59){
188
            minutes =  minutes % 60;
189
            hours+=1;
190
        }
191
        if (hours >= 24){
192
            hours-=24;
193
        }
194
        return  Clock(hours, minutes);
195
196
    }
197
    /////////////////////////////////////////////////////////////////////////////////////
198
    Clock&  operator += (const Clock& c){
199
        unsigned int minutes, hours;
200
        minutes = m_min+ c.m_min;
201
        hours = m_h + c.m_h;
202
        if (minutes >59){
203
            minutes =  minutes % 60;
204
            hours+=1;
205
        }
206
        if (hours >= 24){
207
            hours-=24;
208
        }
209
        this->m_h = hours;
210
        this->m_min = minutes;
211
        return *this;
212
213
    }
214
    /////////////////////////////////////////////////////////////////////////////////////
215
216
    unsigned int toSeconds(){
217
        return toSeconds(Clock(this->m_h, this->m_min) );
218
    }
219
    /////////////////////////////////////////////////////////////////////////////////////
220
221
    static unsigned int toSeconds(Clock t){
222
        return ((t.m_h*60) + t.m_min)*60;
223
    }
224
    /////////////////////////////////////////////////////////////////////////////////////
225
226
    static Clock fromSeconds(unsigned int sec){
227
        unsigned int h = sec/3600;
228
        unsigned int min = sec%3600;
229
        min = min/60;
230
        return Clock(h,min);
231
    }
232
    /////////////////////////////////////////////////////////////////////////////////////
233
234
    static Clock periodOfTime(Clock start, Clock end)
235
    {
236
        if (end >= start){
237
            return Clock::fromSeconds(end.toSeconds() - start.toSeconds()  );
238
        }
239
        else{
240
            return Clock::fromSeconds(end.toSeconds() + ( Clock::toSeconds(Clock(23,59))+ 60 - start.toSeconds() ) );
241
        }
242
        //return diff;
243
    }
244
    ////////////////////////////////////////////////////////////////////////////////////
245
    static unsigned int getUnixTime()
246
    {
247
        return static_cast<unsigned int> (std::time(nullptr));
248
    }
249
    /////////////////////////////////////////////////////////////////////////////////////
250
#ifdef BT_TEST
251
    static void setTime_forBT_usage(int h, int m)
252
    {
253
        m_BT_H = h;
254
        m_BT_M = m;
255
    }
256
#endif
257
    /////////////////////////////////////////////////////////////////////////////////////
258
    static Clock getTime()
259
    {
260
#ifdef BT_TEST
261
        return Clock(m_BT_H,m_BT_M);
262
#else
263
        time_t now = time(0);
264
        tm *ltm = localtime(&now);
265
        return Clock( static_cast <unsigned int>(ltm->tm_hour),static_cast <unsigned int>(ltm->tm_min) );
266
#endif
267
    }
268
    /////////////////////////////////////////////////////////////////////////////////////
269
    void stopwatchStart()
270
    {
271
        m_time = std::time(nullptr);
272
    }
273
    /////////////////////////////////////////////////////////////////////////////////////
274
    unsigned int  stopwatchStopAndGetResult()
275
    {
276
        return static_cast<unsigned int>(std::time(nullptr) - m_time);
277
    }
278
};
279
280
enum class STATE {
281
    OFF,
282
    ON,
283
    UNKNOWN,
284
    PLAY,
285
    PAUSE,
286
    STOP,
287
    ACTIVE,
288
    DEACTIVE,
289
    WORKING,
290
    DEFINE,
291
    UNDEFINE,
292
    LOCK,
293
    UNLOCK,
294
    EMPTY,
295
    FULL,
296
    SEND_OK,
297
    SEND_NOK
298
    //WARNING remember add new state to stateToString() usefull.cpp
299
};
300
301
302
std::string stateToString(STATE s);
303
STATE stringToState(const std::string& s);
304
305
#endif
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandhandler.cpp
Line
Count
Source
1
#include <iostream>
2
#include "../../libs/emoji/emoji.h"
3
#include "commandhandler.h"
4
#include "commandClass/command_mpd.h"
5
#include "commandClass/commandrs232.h"
6
#include "commandClass/command_uptime.h"
7
#include "commandClass/command_big.h"
8
#include "commandClass/command_clock.h"
9
#include "commandClass/command_hello.h"
10
#include "commandClass/command_help.h"
11
#include "commandClass/command_ip.h"
12
#include "commandClass/command_put.h"
13
#include "commandClass/command_sleep.h"
14
#include "commandClass/command_ok.h"
15
#include "commandClass/command_show.h"
16
#include "commandClass/command_idom.h"
17
#include "commandClass/command_program.h"
18
#include "commandClass/commandexit.h"
19
#include "commandClass/commandtest.h"
20
#include "commandClass/command_log.h"
21
#include "commandClass/command_state.h"
22
#include "commandClass/command_ardu.h"
23
24
commandHandler::commandHandler(thread_data * my_data)
25
7
{
26
7
    std::unique_ptr <command> test(new commandTEST("test") );
27
7
    commandMap.insert( std::make_pair(test->getCommandName(),std::move( test )) );
28
7
29
7
    std::unique_ptr <command> program(new command_program("program") );
30
7
    commandMap.insert( std::make_pair(program->getCommandName(),std::move( program )) );
31
7
32
7
    std::unique_ptr <command> eexit(new commandEXIT("exit"));
33
7
    commandMap.insert( std::make_pair(eexit->getCommandName(),std::move( eexit )) );
34
7
35
7
    std::unique_ptr <command> MPD(new command_mpd("MPD"));
36
7
    commandMap.insert(std::make_pair(MPD->getCommandName(), std::move (MPD)));
37
7
38
7
    std::unique_ptr <command> RS232 (new commandRS232("RS232"));
39
7
    commandMap.insert(std::make_pair(RS232->getCommandName(), std::move(RS232)));
40
7
41
7
    std::unique_ptr <command> uptime (new command_UPTIME("uptime"));
42
7
    commandMap.insert(std::make_pair(uptime->getCommandName(), std::move(uptime)));
43
7
44
7
    std::unique_ptr <command> big (new command_big("big"));
45
7
    commandMap.insert(std::make_pair(big->getCommandName(), std::move(big)));
46
7
47
7
    std::unique_ptr <command> clock (new command_clock("clock"));
48
7
    commandMap.insert(std::make_pair(clock->getCommandName(), std::move(clock)));
49
7
50
7
    std::unique_ptr <command> hello (new command_hello("hello"));
51
7
    commandMap.insert(std::make_pair(hello->getCommandName(), std::move(hello)));
52
7
53
7
    std::unique_ptr <command> help (new command_help("help"));
54
7
    commandMap.insert(std::make_pair(help->getCommandName(), std::move(help)));
55
7
56
7
    std::unique_ptr <command> ip (new command_ip("ip"));
57
7
    commandMap.insert(std::make_pair(ip->getCommandName(), std::move(ip)));
58
7
59
7
    std::unique_ptr <command> ok (new command_ok("ok"));
60
7
    commandMap.insert(std::make_pair(ok->getCommandName(), std::move(ok)));
61
7
62
7
    std::unique_ptr <command> show (new command_show("show"));
63
7
    commandMap.insert(std::make_pair(show->getCommandName(), std::move(show)));
64
7
65
7
    std::unique_ptr <command> sleep (new command_sleep("sleep"));
66
7
    commandMap.insert(std::make_pair(sleep->getCommandName(), std::move(sleep)));
67
7
68
7
    std::unique_ptr <command> put (new command_put("put"));
69
7
    commandMap.insert(std::make_pair(put->getCommandName(), std::move(put)));
70
7
71
7
    std::unique_ptr <command> iDom (new command_iDom("iDom"));
72
7
    commandMap.insert(std::make_pair(iDom->getCommandName(), std::move(iDom)));
73
7
74
7
    std::unique_ptr <command> log (new command_log("log"));
75
7
    commandMap.insert(std::make_pair(log->getCommandName(), std::move(log)));
76
7
77
7
    std::unique_ptr <command> state (new command_state("state"));
78
7
    commandMap.insert(std::make_pair(state->getCommandName(), std::move(state)));
79
7
80
7
    std::unique_ptr <command> ardu (new command_ardu("ardu", my_data));
81
7
    commandMap.insert(std::make_pair(ardu->getCommandName(), std::move(ardu)));
82
7
83
7
    this->my_data = my_data;
84
7
    this->my_data->commandMapPtr = &commandMap;
85
7
}
86
87
commandHandler::~commandHandler()
88
7
{
89
7
    puts("commandHandler::~commandHandler()");
90
7
}
91
92
std::string commandHandler::run(std::vector<std::string> &v, thread_data *my_data)
93
3
{
94
3
    if (commandMap.find(v[0]) == commandMap.end()){
95
1
        std::fstream log;
96
1
        log.open( "/mnt/ramdisk/command.txt", std::ios::binary | std::ios::in | std::ios::out|std::ios::app );
97
1
        log << v[0] << std::endl;
98
1
        log.close();
99
1
        return EMOJI::emoji(E_emoji::WARNING_SIGN)+" unknown command: "+ v[0];
100
1
    }
101
2
    else{
102
2
        return commandMap[v[0]]->execute(v,my_data);
103
2
    }
104
3
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDom_server_OOP.h
Line
Count
Source
1
#ifndef GLOBAL_H
2
#define GLOBAL_H
3
4
#include <iostream>
5
#include <fstream>
6
#include <string>
7
#include <cstdlib>
8
#include <pthread.h>
9
#include <stdio.h>
10
#include <stdlib.h>
11
#include <sys/socket.h>
12
#include <sys/types.h>
13
#include <netinet/in.h>
14
#include <vector>
15
#include <thread>
16
#include <arpa/inet.h>
17
#include <netinet/in.h>
18
#include <unistd.h>
19
#include <sys/fcntl.h>
20
#include <unistd.h>
21
#include <errno.h>
22
#include <signal.h>
23
#include <time.h>
24
#include <wiringPi.h>
25
#include <chrono>
26
#include <array>
27
28
// MOJE BIBLIOTEKI
29
#include "KEY/key.h"
30
#include "logger/logger.hpp"
31
#include "files_tree/files_tree.h"
32
#include "menu_tree/menu_tree.h"
33
#include "LCD_c/lcd_c.h"
34
#include "command/command.h"
35
#include "../libs/event_counters/event_counters_handler.h"
36
#include "iDomTools/idomtools.h"
37
#include "iDomStatus/idomstatus.h"
38
#include "iDomSaveState/idom_save_state.h"
39
40
126
#define log_file_cout  f_log //std::cout zmien f_log na std::cout i bedzie wypisywac na ekran
41
62
#define log_file_mutex f_log
42
43
enum class iDomStateEnum{
44
    CLOSE = 0,
45
    RELOAD,
46
    ERROR,
47
    WORKING,
48
    HARD_RELOAD
49
};
50
51
namespace iDomConst
52
{
53
constexpr int MAX_CONNECTION = 10;
54
constexpr int FREE  = 1;
55
constexpr int RS232 = 11;
56
constexpr int CLOCK = 12;
57
constexpr int ok    = 0;
58
constexpr int GPIO_SPIK = 21;
59
constexpr int GPIO_PRINTER = 22;
60
constexpr int BUTTON_PIN = 25;
61
}
62
struct ALERT
63
{
64
    Clock time;
65
    STATE state = STATE::DEACTIVE;
66
    unsigned int fromVolume = 48;
67
    unsigned int toVolume = 58;
68
    unsigned int radioID = 8;
69
};
70
71
extern std::string _logfile;
72
extern Logger log_file_mutex;
73
extern std::string buffer;
74
75
enum class TEMPERATURE_STATE;
76
enum class PILOT_KEY;
77
78
struct MPD_info{
79
    std::string title   = "NULL";
80
    std::string radio   = "NULL";
81
    std::string artist  = "NULL";
82
    int volume = 0;
83
    bool isPlay = false;
84
    int currentSongID = 0;
85
    std::vector <std::string> songList = {"NULL"};
86
};
87
struct s_pointer{
88
    unsigned int *ptr_who;
89
    int32_t *ptr_buf;
90
};
91
92
struct Thread_array_struc {
93
    std::thread thread;
94
    std::thread::id thread_ID = std::thread::id(0);
95
    std::string thread_name;
96
    int thread_socket = 0;
97
};
98
99
struct address_another_servers {
100
    int id;
101
    std::string SERVER_IP;
102
};
103
104
struct FTP_SERVER{
105
    std::string URL;
106
    std::string user;
107
    std::string pass;
108
};
109
struct iDOM_STATE{
110
    STATE houseState = STATE::UNDEFINE;
111
112
};
113
114
struct config{
115
    std::string portRS232;
116
    std::string portRS232_clock;
117
    std::string BaudRate;
118
    std::string RFLinkPort;
119
    std::string RFLinkBaudRate;
120
    int PORT;
121
    std::string SERVER_IP;
122
    std::string MPD_IP;
123
    std::string MOVIES_DB_PATH;
124
    std::string MENU_PATH;
125
    std::string THREAD_MPD   = "NULL";
126
    std::string THREAD_IRDA  = "NULL";
127
    std::string THREAD_CRON  = "NULL";
128
    std::string THREAD_RS232 = "NULL";
129
    std::string THREAD_DUMMY = "NULL";
130
    std::string TS_KEY= " gg ";
131
    std::string cameraLedON = "";
132
    std::string cameraLedOFF ="";
133
    std::string cameraURL="";
134
    std::string facebookAccessToken = "";
135
    std::string viberToken = "NULL";
136
    std::string viberAvatar;
137
    std::vector <std::string> viberReceiver;
138
    std::string viberSender;
139
    std::string radio433MHzConfigFile;
140
    std::string omxplayerFile = "NULL";
141
    int ID_server = 0;
142
    int v_delay;
143
    bool encrypted = true;
144
145
    FTP_SERVER ftpServer;
146
    std::string lightningApiURL = "NULL";
147
    std::string saveFilePath = "NULL";
148
};
149
150
struct LED_Strip{
151
    std::string from;
152
    std::string to;
153
    std::string R;
154
    std::string G;
155
    std::string B;
156
    std::string colorName;
157
158
    LED_Strip (int from, int to, int r, int g, int b, std::string colorName = "NULL"):from(std::to_string(from)),
159
        to(std::to_string(to)),
160
        R(std::to_string(r)),
161
        G(std::to_string(g)),
162
        B(std::to_string(b)),
163
        colorName(colorName)
164
    {
165
166
    }
167
    LED_Strip (const std::string& from,
168
               const std::string& to,
169
               const std::string& r,
170
               const std::string& g,
171
               const std::string& b,
172
               const std::string& colorName = "NULL"):
173
        from(from),
174
        to(to),
175
        R(r),
176
        G(g),
177
        B(b),
178
        colorName(colorName)
179
    {
180
181
    }
182
183
    void set (const std::string& from,
184
              const std::string& to,
185
              const std::string& r,
186
              const std::string& g,
187
              const std::string& b,
188
              const std::string& colorName = "NULL")
189
    {
190
        this->from =from;
191
        this->to = to;
192
        R = r;
193
        G = g;
194
        B = b;
195
        this->colorName =colorName;
196
    }
197
198
    void set (int from, int to, int r, int g, int b, std::string colorName = "NULL"){
199
        this->from = std::to_string(from);
200
        this->to = std::to_string(to);
201
        R = std::to_string(r);
202
        G = std::to_string(g);
203
        B = std::to_string(b);
204
        this->colorName =colorName;
205
    }
206
207
    std::string getColorName() const{
208
        return colorName;
209
    }
210
211
    std::string get(unsigned int _from, unsigned int _to) const{
212
        if (_from != 0 || _to != 60){
213
            return "LED:["+std::to_string(_from)+"-"+std::to_string(_to)+"-"+R+"-"+G+"-"+B+"];";
214
        }
215
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
216
    }
217
218
    std::string makeCommand(const std::string& from,
219
                            const std::string& to,
220
                            const std::string& R,
221
                            const std::string& G,
222
                            const std::string& B){
223
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
224
    }
225
};
226
227
struct pilot_led{
228
    unsigned int counter=0;
229
    std::vector<LED_Strip> colorLED   = { LED_Strip(1,60,237,145,33 ,"carrot orange"),
230
                                          LED_Strip(1,60,255,0,0    ,"red"),
231
                                          LED_Strip(1,60,0,255,0    ,"green"),
232
                                          LED_Strip(1,60,0,0,255    ,"blue"),
233
                                          LED_Strip(1,60,255,255,255,"white"),
234
                                          LED_Strip(1,60,255,255,0  ,"yellow"),
235
                                          LED_Strip(1,60,0,255,255  ,"cyan"),
236
                                          LED_Strip(1,60,255,0,255  ,"magenta")
237
                                        };
238
};
239
240
class command; // for struc thread_data req
241
class iDomTOOLS;
242
class RADIO_EQ_CONTAINER;
243
class RFLinkHandler;
244
245
struct thread_data{
246
    int s_client_sock;
247
    struct sockaddr_in from;
248
    struct config *server_settings = NULL;
249
    struct s_pointer pointer;
250
    LCD_c *mainLCD = NULL;
251
    files_tree *main_tree = NULL;
252
    menu_tree *main_MENU = NULL;
253
    iDomTOOLS *main_iDomTools = NULL;
254
    RFLinkHandler *main_RFLink = NULL;
255
    std::array<Thread_array_struc, iDomConst::MAX_CONNECTION> *main_THREAD_arr = NULL;
256
    time_t start;
257
    time_t now_time;
258
    int sleeper;
259
    std::map <std::string, std::unique_ptr <KEY> > key_map;
260
    MPD_info *ptr_MPD_info = NULL;
261
    pilot_led * ptr_pilot_led = NULL;
262
    std::map <std::string, std::unique_ptr<command> >* commandMapPtr = NULL;
263
    event_counters_handler myEventHandler;
264
    std::string encriptionKey = "40%";
265
    iDomSTATUS *main_iDomStatus;
266
    iDOM_STATE idom_all_state;
267
    ALERT alarmTime;
268
    std::shared_ptr<RADIO_EQ_CONTAINER> main_REC;
269
    iDomStateEnum iDomProgramState = iDomStateEnum::WORKING;
270
};
271
272
struct thread_data_rs232{
273
    std::string portRS232;
274
    std::string portRS232_clock;
275
    std::string BaudRate;
276
    struct s_pointer pointer;
277
};
278
279
#endif // GLOBAL_H
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandhandlerroot.cpp
Line
Count
Source
1
#include "commandhandlerroot.h"
2
#include "commandClass/command_cmd.h"
3
#include "commandClass/command_event.h"
4
#include "commandClass/command_433mhz.h"
5
6
commandHandlerRoot::commandHandlerRoot(thread_data * my_data): commandHandler(my_data)
7
7
{
8
7
    std::unique_ptr <command> cmd (new command_cmd("cmd"));
9
7
    commandMap.insert(std::make_pair(cmd->getCommandName(), std::move(cmd)));
10
7
11
7
    std::unique_ptr <command> event (new command_event("event"));
12
7
    commandMap.insert(std::make_pair(event->getCommandName(), std::move(event)));
13
7
14
7
    std::unique_ptr <command> r_433MHz (new command_433MHz("433MHz"));
15
7
    commandMap.insert(std::make_pair(r_433MHz->getCommandName(), std::move(r_433MHz)));
16
7
}
17
18
commandHandlerRoot::~commandHandlerRoot()
19
7
{
20
7
    puts("commandHandlerRoot::~commandHandlerRoot()");
21
7
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/logger/logger.hpp
Line
Count
Source
1
/*
2
 * logger.hpp
3
 *
4
 *
5
 * Logger Library Header
6
 *
7
 *
8
 * Copyright (C) 2013-2014  Bryant Moscon - bmoscon@gmail.com
9
 *
10
 * Permission is hereby granted, free of charge, to any person obtaining a copy
11
 * of this software and associated documentation files (the "Software"), to
12
 * deal in the Software without restriction, including without limitation the
13
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
14
 * sell copies of the Software, and to permit persons to whom the Software is
15
 * furnished to do so, subject to the following conditions:
16
 *
17
 * 1. Redistributions of source code must retain the above copyright notice,
18
 *    this list of conditions, and the following disclaimer.
19
 *
20
 * 2. Redistributions in binary form must reproduce the above copyright notice,
21
 *    this list of conditions and the following disclaimer in the documentation
22
 *    and/or other materials provided with the distribution, and in the same
23
 *    place and form as other copyright, license and disclaimer information.
24
 *
25
 * 3. The end-user documentation included with the redistribution, if any, must
26
 *    include the following acknowledgment: "This product includes software
27
 *    developed by Bryant Moscon (http://www.bryantmoscon.org/)", in the same
28
 *    place and form as other third-party acknowledgments. Alternately, this
29
 *    acknowledgment may appear in the software itself, in the same form and
30
 *    location as other such third-party acknowledgments.
31
 *
32
 * 4. Except as contained in this notice, the name of the author, Bryant Moscon,
33
 *    shall not be used in advertising or otherwise to promote the sale, use or
34
 *    other dealings in this Software without prior written authorization from
35
 *    the author.
36
 *
37
 *
38
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
41
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
42
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
44
 * THE SOFTWARE.
45
 *
46
 */
47
#ifndef __LOGGER__
48
#define __LOGGER__
49
50
#include <fstream>
51
#include <cassert>
52
#include <ctime>
53
#include <sstream>
54
55
// Log levels
56
typedef enum {
57
    US =0,
58
    VERBOSE,
59
    DEBUG,
60
    INFO,
61
    WARNING,
62
    ERROR,
63
    CRITICAL,
64
    FATAL
65
} logger_level;
66
67
class Logger : public std::ostringstream {
68
public:
69
70
    explicit Logger(const char *f);
71
    explicit Logger(const std::string& f);
72
    Logger (const Logger &);
73
    Logger &operator= (const Logger &);
74
    ~Logger();
75
    static pthread_mutex_t mutex_log;
76
77
    void set_level(const logger_level& level);
78
    void flush();
79
    void mutex_lock();
80
    void mutex_unlock();
81
82
    template <typename T>
83
    Logger& operator<<(const T& t)
84
84
    {
85
84
        *static_cast<std::ostringstream *>(this) << t;
86
84
        return (*this);
87
84
    }
_ZN6LoggerlsINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEERS_RKT_
Line
Count
Source
84
73
    {
85
73
        *static_cast<std::ostringstream *>(this) << t;
86
73
        return (*this);
87
73
    }
_ZN6LoggerlsIA32_cEERS_RKT_
Line
Count
Source
84
6
    {
85
6
        *static_cast<std::ostringstream *>(this) << t;
86
6
        return (*this);
87
6
    }
_ZN6LoggerlsIA28_cEERS_RKT_
Line
Count
Source
84
4
    {
85
4
        *static_cast<std::ostringstream *>(this) << t;
86
4
        return (*this);
87
4
    }
Unexecuted instantiation: _ZN6LoggerlsIA36_cEERS_RKT_
_ZN6LoggerlsIA47_cEERS_RKT_
Line
Count
Source
84
1
    {
85
1
        *static_cast<std::ostringstream *>(this) << t;
86
1
        return (*this);
87
1
    }
88
89
    Logger& operator<<(const logger_level& level);
90
    typedef Logger& (* LoggerManip)(Logger&);
91
    Logger& operator<<(LoggerManip m);
92
93
private:
94
    std::string get_time() const;
95
    inline const char* level_str(const logger_level& level);
96
public:
97
    std::ofstream _file;
98
private:
99
    std::ostream& _log;
100
    logger_level _level;
101
    logger_level _line_level;
102
};
103
104
105
namespace std { 
106
inline Logger& endl(Logger& out)
107
{
108
    out.put('\n');
109
    out.flush();
110
    return (out);
111
}
112
}// end namespace std
113
114
#endif
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/commandhandlerrs232.cpp
Line
Count
Source
1
#include "commandhandlerrs232.h"
2
#include "commandClass/command_cmd.h"
3
#include "commandClass/command_event.h"
4
5
6
commandHandlerRS232::commandHandlerRS232(thread_data *my_data):commandHandlerRoot(my_data)
7
1
{
8
1
9
1
}
10
11
commandHandlerRS232::~commandHandlerRS232()
12
1
{
13
1
    puts("commandHandlerRS232::~commandHandlerRS232()");
14
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDomTools/idomtools.cpp
Line
Count
Source (jump to first uncovered line)
1
#include <algorithm>
2
#include <fstream>
3
#include <string>
4
#include <typeinfo>
5
6
#include "idomtools.h"
7
#include "../functions/functions.h"
8
#include "../../libs/emoji/emoji.h"
9
#include "../../libs/Statistic/statistic.h"
10
#include "../CRON/cron.hpp"
11
#include "../RADIO_433_eq/radio_433_eq.h"
12
#include "json.hpp"
13
#include "../thread_functions/iDom_thread.h"
14
15
iDomTOOLS::iDomTOOLS(thread_data *myData): key(myData->server_settings->TS_KEY)
16
192
{
17
192
    puts("iDomTOOLS::iDomTOOLS()");
18
192
    my_data = myData;
19
192
20
192
    //////////////////////////////////// temeprature /////////////////
21
192
22
192
    allThermometer.add("inside");
23
192
    allThermometer.add("outside");
24
192
    allThermometerUpdate.add("inside");
25
192
    allThermometerUpdate.add("outside");
26
192
    /////////////////////////////////////////////////////////////////
27
#ifndef BT_TEST
28
    pinMode(iDomConst::GPIO_SPIK, OUTPUT); // gpio pin do zasilania glosnikow
29
    digitalWrite(iDomConst::GPIO_SPIK,LOW);
30
    pinMode(iDomConst::GPIO_PRINTER,OUTPUT); /// gpio pin do zsilania drukarki
31
    digitalWrite(iDomConst::GPIO_PRINTER,LOW);
32
    pinMode(iDomConst::BUTTON_PIN, INPUT); // gpio pin przycisku
33
34
    if (wiringPiISR (iDomConst::BUTTON_PIN, INT_EDGE_BOTH, &useful_F::button_interrupt) < 0 ) {
35
36
        log_file_cout.mutex_lock();
37
        log_file_cout << CRITICAL <<"Unable to setup ISR RISING "<<std::endl;
38
        log_file_cout.mutex_unlock();
39
40
    }
41
#endif
42
192
    my_data->main_iDomStatus->addObject("cameraLED",STATE::UNKNOWN);
43
192
    my_data->main_iDomStatus->addObject("printer",STATE::OFF);
44
192
    my_data->main_iDomStatus->addObject("speakers",STATE::OFF);
45
192
    my_data->main_iDomStatus->addObject("alarm",STATE::DEACTIVE);
46
192
    my_data->main_iDomStatus->addObject("KODI",STATE::DEACTIVE);
47
192
48
192
    ///////// setup viber api
49
192
    m_viber.setAvatar(my_data->server_settings->viberAvatar);
50
192
    m_viber.setAccessToken(my_data->server_settings->viberToken);
51
192
    m_viber.setURL("https://chatapi.viber.com/pa/send_message");
52
192
    ///////// setup faceboook api
53
192
    m_facebook.setAccessToken(my_data->server_settings->facebookAccessToken);
54
192
55
192
    //////// button 433MHz
56
192
    buttonPointerVector = my_data->main_REC->getButtonPointerVector();
57
192
58
192
    lastButton433MHzLockUnlockTime = Clock::getTime() + Clock(23,58);
59
192
60
192
}
61
62
TEMPERATURE_STATE iDomTOOLS::hasTemperatureChange(const std::string& thermometerName, double reference, double histereza )
63
16
{
64
16
    reference += 0.0055;
65
16
    const auto newTemp = allThermometer.getTemp(thermometerName);
66
16
    const auto oldTemp = allThermometer.getOldTemp(thermometerName);
67
16
    const auto lastState = allThermometer.getLastState(thermometerName);
68
16
    if (newTemp >= reference + histereza &&
69
16
            oldTemp < reference + histereza &&
70
16
            lastState != TEMPERATURE_STATE::Over)
71
16
    {
72
3
        my_data->myEventHandler.run("test")->addEvent("over: new "+ to_string_with_precision(newTemp)+" old: "
73
3
                                                      +to_string_with_precision(oldTemp)+" ref: "
74
3
                                                      +to_string_with_precision(reference));
75
3
        allThermometer.setState(thermometerName, TEMPERATURE_STATE::Over);
76
3
        return TEMPERATURE_STATE::Over;
77
3
    }
78
16
    else if (newTemp <= reference - histereza &&
79
13
             oldTemp > reference - histereza &&
80
13
             lastState != TEMPERATURE_STATE::Under)
81
13
    {
82
3
        my_data->myEventHandler.run("test")->addEvent("under: new "+to_string_with_precision(newTemp)+" old: "
83
3
                                                      +to_string_with_precision(oldTemp)+" ref: "
84
3
                                                      +to_string_with_precision(reference));
85
3
        allThermometer.setState(thermometerName, TEMPERATURE_STATE::Under);
86
3
        return TEMPERATURE_STATE::Under;
87
3
    }
88
16
89
16
    my_data->myEventHandler.run("test")->addEvent("noChanges: new "+to_string_with_precision(newTemp)+" old: "
90
10
                                                  +to_string_with_precision(oldTemp)+" ref: "+to_string_with_precision(reference));
91
10
92
10
    allThermometer.setState(thermometerName, TEMPERATURE_STATE::NoChanges);
93
10
    return TEMPERATURE_STATE::NoChanges;
94
16
}
95
96
void iDomTOOLS::sendSMSifTempChanged(const std::string& thermomethernName, int reference)
97
16
{
98
16
    TEMPERATURE_STATE status = hasTemperatureChange(thermomethernName,reference,0.5);
99
16
    std::string m = "temperature "+thermomethernName+" over "+ EMOJI::emoji(E_emoji::NORTH_EAST_ARROW)
100
16
            + to_string_with_precision(reference);
101
16
102
16
    if (status == TEMPERATURE_STATE::Over){
103
3
        my_data->myEventHandler.run("temperature")->addEvent(m);
104
3
        if (reference < 2){
105
1
            sendViberMsg(m,my_data->server_settings->viberReceiver.at(0),my_data->server_settings->viberSender);
106
1
            sendViberMsg(m,my_data->server_settings->viberReceiver.at(1),my_data->server_settings->viberSender);
107
1
        }
108
3
        else{
109
2
            sendViberMsg(m,my_data->server_settings->viberReceiver.at(0),my_data->server_settings->viberSender);
110
2
        }
111
3
    }
112
16
    else if (status == TEMPERATURE_STATE::Under){
113
3
        m ="temperature " + thermomethernName+" under "+EMOJI::emoji(E_emoji::SOUTH_EAST_ARROW)
114
3
                +to_string_with_precision(reference);
115
3
        my_data->myEventHandler.run("temperature")->addEvent(m);
116
3
        if (reference < 2){
117
2
            sendViberPicture(m,"http://canacopegdl.com/images/cold/cold-14.jpg",
118
2
                             my_data->server_settings->viberReceiver.at(0),
119
2
                             my_data->server_settings->viberSender);
120
2
            sendViberPicture(m,"http://canacopegdl.com/images/cold/cold-14.jpg",
121
2
                             my_data->server_settings->viberReceiver.at(1),
122
2
                             my_data->server_settings->viberSender);
123
2
            postOnFacebook(m,"http://canacopegdl.com/images/cold/cold-14.jpg");
124
2
        }
125
3
        else {
126
1
            sendViberMsg(m,my_data->server_settings->viberReceiver.at(0),
127
1
                         my_data->server_settings->viberSender);
128
1
        }
129
3
    }
130
13
    else{
131
10
        //my_data->myEventHandler.run("unknown")->addEvent("temperatura nie przeszla przez "+to_string_with_precision(reference));
132
10
    }
133
16
}
134
135
std::string iDomTOOLS::getThermoStats(const std::string& name)
136
2
{
137
2
    return allThermometerUpdate.getStatsByName(name);
138
2
}
139
140
void iDomTOOLS::updateTemperatureStats()
141
6
{
142
6
    auto v = getTemperature();
143
6
    allThermometerUpdate.updateAll(&v);
144
6
    allThermometerUpdate.updateStats("outside");
145
6
    allThermometerUpdate.updateStats("inside");
146
6
147
6
    if( true == allThermometerUpdate.isMoreDiff("outside",2.1)){
148
2
        auto data = allThermometerUpdate.getLast2("outside");
149
2
        std::string msg = "alarm roznicy temeratur na polu! " + to_string_with_precision(data.first) +" na "+
150
2
                to_string_with_precision(data.second);
151
2
152
2
        if (data.first > data.second){
153
1
            msg += " temperatura maleje " + EMOJI::emoji(E_emoji::CHART_WITH_DOWNWARDS_TREND);
154
1
        }
155
2
        else{
156
1
            msg += " temperatura rośnie " + EMOJI::emoji(E_emoji::CHART_WITH_UPWARDS_TREND);
157
1
        }
158
2
159
2
        sendViberMsg(msg,
160
2
                     my_data->server_settings->viberReceiver.at(0),
161
2
                     my_data->server_settings->viberSender);
162
2
163
2
        log_file_mutex.mutex_lock();
164
2
        log_file_cout << WARNING << msg << std::endl;
165
2
        log_file_mutex.mutex_unlock();
166
2
    }
167
6
    if( true == allThermometerUpdate.isMoreDiff("inside",2.1)){
168
2
        auto data = allThermometerUpdate.getLast2("inside");
169
2
        std::string msg = "alarm roznicy temeratur na mieszkaniu! " + to_string_with_precision(data.first) +" na "+
170
2
                to_string_with_precision(data.second);
171
2
172
2
        if (data.first > data.second){
173
1
            msg += " temperatura maleje " + EMOJI::emoji(E_emoji::CHART_WITH_DOWNWARDS_TREND);
174
1
        }
175
2
        else{
176
1
            msg += " temperatura rośnie " + EMOJI::emoji(E_emoji::CHART_WITH_UPWARDS_TREND);
177
1
        }
178
2
179
2
        sendViberMsg(msg,
180
2
                     my_data->server_settings->viberReceiver.at(0),
181
2
                     my_data->server_settings->viberSender);
182
2
183
2
        log_file_mutex.mutex_lock();
184
2
        log_file_cout << WARNING << msg << std::endl;
185
2
        log_file_mutex.mutex_unlock();
186
2
    }
187
6
}
188
189
void iDomTOOLS::turnOnSpeakers()
190
8
{
191
8
    if (useful_F::myStaticData->idom_all_state.houseState == STATE::UNLOCK)
192
8
    {
193
4
        digitalWrite(iDomConst::GPIO_SPIK, HIGH);
194
4
        useful_F::myStaticData->main_iDomStatus->setObjectState("speakers",STATE::ON);
195
4
    }
196
8
    else{
197
4
        useful_F::myStaticData->myEventHandler.run("speakers")->addEvent("speakers can not start due to home state: "+
198
4
                                                                         stateToString(useful_F::myStaticData->idom_all_state.houseState));
199
4
    }
200
8
    useful_F::myStaticData->main_iDomTools->saveState_iDom();
201
8
}
202
203
void iDomTOOLS::turnOffSpeakers()
204
6
{
205
6
    digitalWrite(iDomConst::GPIO_SPIK, LOW);
206
6
    useful_F::myStaticData->main_iDomStatus->setObjectState("speakers",STATE::OFF);
207
6
    // useful_F::myStaticData->main_iDomTools->saveState_iDom();
208
6
}
209
210
void iDomTOOLS::turnOnPrinter()
211
5
{
212
5
    if (my_data->idom_all_state.houseState == STATE::UNLOCK)
213
5
    {
214
4
        digitalWrite(iDomConst::GPIO_PRINTER,HIGH);
215
4
        my_data->myEventHandler.run("230V")->addEvent("230v drukarki ON");
216
4
        my_data->main_iDomStatus->setObjectState("printer",STATE::ON);
217
4
    }
218
5
    else{
219
1
        my_data->myEventHandler.run("230V")->addEvent("Printer can not start due to home state: "+
220
1
                                                      stateToString(my_data->idom_all_state.houseState));
221
1
    }
222
5
}
223
224
void iDomTOOLS::turnOffPrinter()
225
6
{
226
6
    digitalWrite(iDomConst::GPIO_PRINTER,LOW);
227
6
    my_data->myEventHandler.run("230V")->addEvent("230v drukarki OFF");
228
6
    my_data->main_iDomStatus->setObjectState("printer",STATE::OFF);
229
6
}
230
231
PIN_STATE iDomTOOLS::getPinState(int pin_number)
232
7
{
233
7
    int pin_state = digitalRead(pin_number);
234
7
    switch (pin_state){
235
3
    case 0:
236
3
        return PIN_STATE::LOW_STATE;
237
3
    case 1:
238
2
        return PIN_STATE::HIGH_STATE;
239
3
    default:
240
2
        return PIN_STATE::UNKNOWN_STATE;
241
0
    }
242
7
}
243
244
void iDomTOOLS::turnOnOffPrinter()
245
4
{
246
4
    PIN_STATE pinState = getPinState(iDomConst::GPIO_PRINTER);
247
4
    switch (pinState){
248
4
    case PIN_STATE::HIGH_STATE:
249
1
        turnOffPrinter();
250
1
        my_data->mainLCD->set_lcd_STATE(10);
251
1
        my_data->mainLCD->printString(true,0,0,"230V OFF");
252
1
        break;
253
2
    case PIN_STATE::LOW_STATE:
254
2
        turnOnPrinter();
255
2
        my_data->mainLCD->set_lcd_STATE(10);
256
2
        my_data->mainLCD->printString(true,0,0,"230V ON");
257
2
        break;
258
1
    default:
259
1
        puts("def");
260
1
261
1
        log_file_mutex.mutex_lock();
262
1
        log_file_cout << CRITICAL << " blad odczytu stanu pinu zasilania drukarki "<< std::endl;
263
1
        log_file_mutex.mutex_unlock();
264
4
    }
265
4
}
266
267
void iDomTOOLS::turnOnOff433MHzSwitch(const std::string& name)
268
4
{
269
4
    STATE listwaState = my_data->main_iDomStatus->getObjectState(name);
270
4
    RADIO_SWITCH *m_switch = dynamic_cast<RADIO_SWITCH*>(my_data->main_REC->getEqPointer(name));
271
4
    if (listwaState == STATE::ON){
272
2
        my_data->mainLCD->set_lcd_STATE(10);
273
2
        my_data->mainLCD->printString(true,0,0,"230V OFF "+name);
274
2
        m_switch->off();
275
2
    }
276
4
    else if (listwaState == STATE::OFF){
277
2
        my_data->mainLCD->set_lcd_STATE(10);
278
2
        my_data->mainLCD->printString(true,0,0,"230V ON "+name);
279
2
        m_switch->on();
280
2
    }
281
4
    saveState_iDom();
282
4
}
283
284
void iDomTOOLS::turnOn433MHzSwitch(std::string name)
285
1
{
286
1
    RADIO_SWITCH *m_switch = dynamic_cast<RADIO_SWITCH*>(my_data->main_REC->getEqPointer(std::move(name)));
287
1
    m_switch->on();
288
1
    //saveState_iDom();
289
1
}
290
291
void iDomTOOLS::turnOff433MHzSwitch(std::string name)
292
4
{
293
4
    RADIO_SWITCH *m_switch = dynamic_cast<RADIO_SWITCH*>(my_data->main_REC->getEqPointer(std::move(name)));
294
4
    m_switch->off();
295
4
}
296
297
void iDomTOOLS::runOnSunset()
298
3
{
299
3
    if (my_data->idom_all_state.houseState == STATE::UNLOCK)
300
3
    {
301
2
        ////switch 433mhz
302
10
        for (auto m_switch : my_data->main_REC->getSwitchPointerVector()){
303
10
            m_switch->onSunset();
304
10
        }
305
2
    }
306
3
    else{
307
1
        my_data->myEventHandler.run("iDom")->addEvent("433MHz can not start due to home state: "+
308
1
                                                      stateToString(my_data->idom_all_state.houseState));
309
1
    }
310
3
}
311
312
void iDomTOOLS::runOnSunrise()
313
4
{
314
4
    if (my_data->idom_all_state.houseState == STATE::UNLOCK)
315
4
    {
316
2
        ////switch 433mhz
317
10
        for (auto m_switch : my_data->main_REC->getSwitchPointerVector()){
318
10
            m_switch->onSunrise();
319
10
        }
320
2
    }
321
4
    else{
322
2
        my_data->myEventHandler.run("iDom")->addEvent("433MHz can not start due to home state: "+
323
2
                                                      stateToString(my_data->idom_all_state.houseState));
324
2
    }
325
4
    my_data->main_iDomTools->ledOFF();
326
4
}
327
328
void iDomTOOLS::lockHome()
329
7
{
330
7
    my_data->idom_all_state.houseState = STATE::LOCK;
331
7
    my_data->main_iDomStatus->setObjectState("house", STATE::LOCK);
332
7
    my_data->main_iDomTools->sendViberPicture("dom zablokownay!",
333
7
                                              "http://cyniu88.no-ip.pl/images/iDom/iDom/lock.jpg",
334
7
                                              my_data->server_settings->viberReceiver.at(0),
335
7
                                              my_data->server_settings->viberSender);
336
7
337
7
    log_file_mutex.mutex_lock();
338
7
    log_file_cout << INFO << "status domu - "+stateToString(my_data->idom_all_state.houseState)<< std::endl;
339
7
    log_file_mutex.mutex_unlock();
340
7
341
7
    saveState_iDom();
342
7
}
343
344
void iDomTOOLS::unlockHome()
345
14
{
346
14
    my_data->idom_all_state.houseState = STATE::UNLOCK;
347
14
    my_data->main_iDomStatus->setObjectState("house", STATE::UNLOCK);
348
14
    my_data->main_iDomTools->sendViberPicture("dom odblokownay!",
349
14
                                              "http://cyniu88.no-ip.pl/images/iDom/iDom/unlock.jpg",
350
14
                                              my_data->server_settings->viberReceiver.at(0),
351
14
                                              my_data->server_settings->viberSender);
352
14
353
14
    log_file_mutex.mutex_lock();
354
14
    log_file_cout << INFO << "status domu - "+stateToString(my_data->idom_all_state.houseState)<< std::endl;
355
14
    log_file_mutex.mutex_unlock();
356
14
357
14
    saveState_iDom();
358
14
}
359
360
void iDomTOOLS::switchActionOnLockHome()
361
1
{
362
1
    ////switch 433mhz
363
5
    for (auto m_switch : my_data->main_REC->getSwitchPointerVector()){
364
5
        m_switch->onLockHome();
365
5
    }
366
1
}
367
368
void iDomTOOLS::switchActionOnUnlockHome()
369
1
{
370
1
    ////switch 433mhz
371
5
    for (auto m_switch : my_data->main_REC->getSwitchPointerVector()){
372
5
        m_switch->onUnlockHome();
373
5
    }
374
1
}
375
376
std::string iDomTOOLS::buttonPressed(const std::string& id)
377
2
{
378
2
    for (auto n : buttonPointerVector){
379
2
        if (id == n->getID()){
380
1
            return n->getName();
381
1
        }
382
2
    }
383
2
    throw "UNKNOWN BUTTON ID: " + std::to_string(id);
384
2
}
385
386
void iDomTOOLS::button433MHzPressedAction(const std::string& name)
387
4
{
388
4
    if (name == "locker"){
389
4
        RADIO_BUTTON* buttonLocker = static_cast<RADIO_BUTTON*>(my_data->main_REC->getEqPointer(name) );
390
4
        button433mhzLockerPressed(buttonLocker);
391
4
    }
392
4
}
393
394
void iDomTOOLS::button433mhzLockerPressed(RADIO_BUTTON *radioButton)
395
10
{
396
10
    static unsigned int counter = 0;
397
10
398
10
    Clock t = Clock::getTime();
399
10
    if (lastButton433MHzLockUnlockTime != t /*|| (lastButton433MHzLockUnlockTime + Clock(0,1)) == t*/)
400
10
    {
401
6
#ifdef BT_TEST
402
6
        std::cout << "LOCKER TEST iDomTOOLS::button433mhzLockerPressed()" <<std::endl;
403
6
#endif
404
6
        lastButton433MHzLockUnlockTime = t;
405
6
        counter = 0;
406
6
        if(my_data->idom_all_state.houseState != STATE::UNLOCK)
407
6
        {
408
2
            buttonUnlockHome();
409
2
            puts("\nodblokuje dom\n");
410
2
            radioButton->setState(STATE::UNLOCK);
411
2
        }
412
6
        else if (my_data->main_iDomStatus->getObjectState("music") == STATE::PLAY)
413
4
        {
414
1
            ledOFF();
415
1
            MPD_stop();
416
1
            turnOffPrinter();
417
1
            radioButton->setState(STATE::STOP);
418
1
            switchActionOnLockHome();
419
1
            //TODO dodać wylaczanie wiatraka
420
1
        }
421
4
        else if (my_data->main_iDomStatus->getObjectState("music") == STATE::STOP)
422
3
        {
423
1
            MPD_play(my_data);
424
1
            switchActionOnUnlockHome();
425
1
            if(isItDay() == false)
426
1
            {
427
1
                ledOn(my_data->ptr_pilot_led->colorLED[2]);
428
1
            }
429
1
            radioButton->setState(STATE::PLAY);
430
1
        }
431
6
    }
432
10
    else
433
10
    {
434
4
        ++counter;
435
4
        if (counter == 2)
436
4
        {
437
2
            buttonLockHome();
438
2
            puts("\nzablokuje dom\n");
439
2
            radioButton->setState(STATE::LOCK);
440
2
        }
441
4
        //#ifdef BT_TEST
442
4
        std::cout << "LOCKER TEST iDomTOOLS::button433mhzLockerPressed()- counter: "<<counter <<std::endl;
443
4
        //#endif
444
4
    }
445
10
446
10
}
447
448
void iDomTOOLS::buttonLockHome()
449
2
{
450
2
    ledOFF();
451
2
    MPD_stop();
452
2
    turnOffPrinter();
453
2
    lockHome();
454
2
}
455
456
void iDomTOOLS::buttonUnlockHome()
457
2
{
458
2
    unlockHome();
459
2
    MPD_play(my_data);
460
2
    if(isItDay() == false){
461
2
        ledOn(my_data->ptr_pilot_led->colorLED[2]);
462
2
    }
463
2
}
464
465
bool iDomTOOLS::isItDay()
466
15
{
467
15
    Clock now = Clock::getTime();
468
15
    if(now < iDomTOOLS::getSunriseClock() || now > iDomTOOLS::getSunsetClock()){
469
14
        return false;
470
14
    }
471
15
    return true;
472
15
}
473
474
std::string iDomTOOLS::getAllDataSunrisesunset()
475
1
{
476
1
    return sun.getAllData();
477
1
}
478
479
CARDINAL_DIRECTIONS::ALARM_INFO iDomTOOLS::getLightningStruct()
480
4
{
481
4
    std::lock_guard<std::mutex> lock(m_lightningMutex);
482
4
    return m_lightningStruct;
483
4
}
484
485
void iDomTOOLS::setLightningStruct(CARDINAL_DIRECTIONS::ALARM_INFO &s)
486
2
{
487
2
    std::lock_guard<std::mutex> lock(m_lightningMutex);
488
2
    //std::cout <<"struktura setowana " << s.data.str() <<std::endl;
489
2
    m_lightningStruct = s;
490
2
491
2
    //std::cout <<"struktura już po setowaniu " << m_lightningStruct.data.str() <<std::endl;
492
2
}
493
494
void iDomTOOLS::checkLightning()
495
1
{
496
1
    nlohmann::json jj = useful_F_libs::getJson(my_data->server_settings->lightningApiURL);
497
1
498
1
    CARDINAL_DIRECTIONS::ALARM_INFO lightningData = lightning.lightningAlert(jj);
499
1
    setLightningStruct(lightningData);
500
1
    bool result = lightning.checkLightningAlert(&lightningData);
501
1
502
1
    if(result == true)
503
1
    {
504
1
505
1
        m_viber.setAvatar("http://cyniu88.no-ip.pl/avatar/lightning.jpg");
506
1
        STATE stateMSG = sendViberMsgBool("UWAGA BURZA KOŁO KRAKOWA! "+EMOJI::emoji(E_emoji::THUNDER_CLOUD_AND_RAIN)
507
1
                                          +"\\n\\n "+lightningData.data.str() ,
508
1
                                          my_data->server_settings->viberReceiver.at(0),
509
1
                                          my_data->server_settings->viberSender);
510
1
511
1
        if(stateMSG == STATE::SEND_NOK){
512
1
            log_file_mutex.mutex_lock();
513
1
            log_file_cout << ERROR << "nie wysłano informacje o burzy"<< std::endl;
514
1
            log_file_mutex.mutex_unlock();
515
1
        }
516
1
        stateMSG = sendViberMsgBool("UWAGA BURZA KOŁO KRAKOWA! "+EMOJI::emoji(E_emoji::THUNDER_CLOUD_AND_RAIN)
517
1
                                    +"\\n\\n "+lightningData.data.str() ,
518
1
                                    my_data->server_settings->viberReceiver.at(1),
519
1
                                    my_data->server_settings->viberSender);
520
1
521
1
        m_viber.setAvatar(my_data->server_settings->viberAvatar);
522
1
        if(stateMSG == STATE::SEND_OK)
523
1
        {
524
0
            log_file_mutex.mutex_lock();
525
0
            log_file_cout << INFO << "wysłano informacje o burzy"<< std::endl;
526
0
            log_file_mutex.mutex_unlock();
527
0
        }
528
1
        else
529
1
        {
530
1
            log_file_mutex.mutex_lock();
531
1
            log_file_cout << ERROR << "nie wysłano informacje o burzy"<< std::endl;
532
1
            log_file_mutex.mutex_unlock();
533
1
        }
534
1
    }
535
1
}
536
537
std::string iDomTOOLS::getSunrise(bool extend )
538
7
{
539
7
    Clock tt = sun.getSunRise();
540
7
    if (extend == true){
541
3
        return "Sunrise time: "+tt.getString();
542
3
    }
543
7
    return tt.getString();
544
7
}
545
546
std::string iDomTOOLS::getSunset(bool extend )
547
7
{
548
7
    Clock tt = sun.getSunSet();
549
7
    if (extend == true){
550
3
        return "Sunset time: "+tt.getString();
551
3
    }
552
7
    return tt.getString();
553
7
}
554
555
Clock iDomTOOLS::getSunsetClock()
556
1
{
557
1
    return sun.getSunSet();
558
1
}
559
560
Clock iDomTOOLS::getSunriseClock()
561
15
{
562
15
    return sun.getSunRise();
563
15
}
564
565
std::string iDomTOOLS::getDayLenght(bool extend )
566
7
{
567
7
    Clock tt = sun.getDayLength();
568
7
    if (extend == true){
569
3
        return "Day Lenght : "+tt.getString();
570
3
    }
571
7
    return tt.getString();
572
7
}
573
574
std::string iDomTOOLS::getWeatherEvent(const std::string& city, unsigned int radius)
575
1
{
576
1
    std::string url = "http://burze.dzis.net/ramka.php?miejscowosc=";
577
1
    url.append(city);
578
1
    url.append("&promien=");
579
1
    url.append(std::to_string(radius));
580
1
    return useful_F_libs::httpPost(url, 10);
581
1
}
582
583
std::vector<WEATHER_ALER> iDomTOOLS::getAlert(std::string data)
584
1
{
585
1
    std::vector<WEATHER_ALER> wAlert;
586
1
    WEATHER_ALER tempWA;
587
1
    std::string d = useful_F_libs::removeHtmlTag(data);
588
1
    std::vector<std::string> vect;
589
1
590
1
    vect = useful_F::split(d,'\n');
591
1
    vect.pop_back();
592
1
    for (auto n : vect)
593
7
    {
594
7
        if (n.find("brak") == std::string::npos)
595
7
        {
596
1
            tempWA.alert = n;
597
1
            tempWA.name = n;
598
1
            tempWA.sended = false;
599
1
            wAlert.push_back(tempWA);
600
1
        }
601
7
    }
602
1
    return {wAlert};
603
1
}
604
605
void iDomTOOLS::textToSpeach(std::vector<std::string> *textVector)
606
4
{
607
4
    if (textVector->empty() ){
608
1
        return;
609
1
    }
610
4
    std::string txt;
611
3
612
7
    for (auto a : *textVector){
613
7
        txt += a;
614
7
    }
615
3
    /////////// start thread TTS - python use ////////////////////////
616
3
    std::string command = " python /home/pi/programowanie/iDom_server_OOP/script/PYTHON/gadacz.py \\"+ txt +"\\";
617
3
    if(my_data->ptr_MPD_info->isPlay){
618
1
619
1
    }
620
3
    else {
621
2
        turnOnSpeakers();
622
2
    }
623
3
624
3
    useful_F::runLinuxCommand(command.c_str());
625
3
626
3
    if(my_data->ptr_MPD_info->isPlay){
627
1
628
1
    }
629
3
    else {
630
2
        turnOffSpeakers();
631
2
    }
632
3
}
633
634
std::string iDomTOOLS::getTextToSpeach()
635
3
{
636
3
    std::vector<std::string> dayL = useful_F::split(getDayLenght(),':');
637
3
    std::stringstream text;
638
3
    std::string smogText = getSmog();
639
3
    int smogInt = std::stoi(smogText);
640
3
    text << "Godzina: " << Clock::getTime().getString();
641
3
    text << ". \nWschód słońca: " << getSunrise();
642
3
    text << ". \nZachód słońca: " << getSunset();
643
3
    text << ". \nDługość dnia: " << dayL[0] << " godzin " << dayL[1] << " minut";
644
3
    text <<". \n";
645
3
    dayL = getTemperature();
646
3
    text << "Temperatura na zewnątrz: " << dayL[1] << " stopnia. \n";
647
3
    text << "Temperatura w pokoju: " << dayL[0] << " stopnia. \n";
648
3
    text << "Smog: " << smogText << " mg/m^3. \n";
649
3
    if (smogInt > 50){
650
0
        int result = smogInt *2;
651
0
        text << "UWAGA! Maksymalna wartość przekroczona " << result << "%.";
652
0
    }
653
3
    return text.str();
654
3
}
655
656
std::vector<std::string> iDomTOOLS::getTemperature()
657
18
{
658
18
    std::vector<std::string> vect = useful_F::split(useful_F::send_to_arduino(my_data,"temperature:22;"),':');
659
18
    return vect;
660
18
}
661
662
std::string iDomTOOLS::getTemperatureString()
663
2
{
664
2
    return useful_F::send_to_arduino(my_data,"temperature:22;");
665
2
}
666
667
std::string iDomTOOLS::getSmog()
668
14
{
669
14
    CURL *curl;
670
14
    CURLcode res;
671
14
    std::string readBuffer;
672
14
    curl = curl_easy_init();
673
14
674
14
    if(curl) {
675
14
        curl_easy_setopt(curl, CURLOPT_URL, "www.smog.krakow.pl");
676
14
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, useful_F_libs::WriteCallback);
677
14
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
678
14
        res = curl_easy_perform(curl);
679
14
        /* Check for errors */
680
14
        if(res != CURLE_OK)
681
14
            fprintf(stderr, "curl_easy_perform() failed: %s\n",
682
0
                    curl_easy_strerror(res));
683
14
684
14
        /* always cleanup */
685
14
        curl_easy_cleanup(curl);
686
14
    }
687
14
    curl_global_cleanup();
688
14
    int start = readBuffer.find("<h2 class=\"polution\">");
689
14
    try {
690
14
        readBuffer = readBuffer.substr(start, 40);
691
14
    }
692
14
    catch (...){
693
0
        log_file_mutex.mutex_lock();
694
0
        log_file_cout << CRITICAL << "wyjatek substr() e getSmog() !!!!!!"<< std::endl;
695
0
        log_file_mutex.mutex_unlock();
696
0
    }
697
14
698
14
    readBuffer = useful_F_libs::find_tag(readBuffer);
699
14
700
14
    return readBuffer;
701
14
}
702
703
void iDomTOOLS::send_temperature_thingSpeak()
704
8
{
705
8
    std::vector<std::string> _temperature = getTemperature();
706
8
    std::string addres = "api.thingspeak.com/update?key=";
707
8
    addres+=key;
708
8
    addres+="&field1=";
709
8
    addres+= _temperature.at(0);
710
8
    // addres.erase(addres.size()-2,addres.size());
711
8
    addres+= "&field3="+_temperature.at(1);
712
8
    addres+="&field2="+getSmog();
713
8
    //////////////////////////////// pozyskanie temperatury
714
8
    allThermometer.updateAll(&_temperature);
715
8
    sendSMSifTempChanged("outside",0);
716
8
    sendSMSifTempChanged("inside",24);
717
8
    std::string s = useful_F_libs::httpPost(addres,10);
718
8
719
8
    if(s == "0"){
720
0
        log_file_mutex.mutex_lock();
721
0
        log_file_cout << CRITICAL << " błąd wysyłania temoeratury na thingspeak: "<< s << std::endl;
722
0
        log_file_mutex.mutex_unlock();
723
0
    }
724
8
}
725
726
void iDomTOOLS::cameraLedON(const std::string& link)
727
3
{
728
3
    Clock t = Clock::getTime();
729
3
    SunRiseSet sun;
730
3
    Clock sunRise, sunSet;
731
3
    sunRise = sun.getSunRise();
732
3
    sunSet = sun.getSunSet();
733
3
    sunSet += Clock(23,30); // +23:30 == -00:30
734
3
    if (t <= sunRise || t >= sunSet){
735
2
        //printf("zapalam leda!\n");
736
2
        std::string s = useful_F_libs::httpPost(link,10);
737
2
        if (s == "ok.\n"){
738
2
            my_data->main_iDomStatus->setObjectState("cameraLED",STATE::ON);
739
2
            // printf("w ifie\n");
740
2
        }
741
2
    }
742
3
    // printf("nie odpalam leda!\n");
743
3
}
744
745
void iDomTOOLS::cameraLedOFF(const std::string& link)
746
3
{
747
3
    std::string s = useful_F_libs::httpPost(link,10);
748
3
    //printf (" camera response '%s' \n", s.c_str());
749
3
    if (s == "ok.\n"){
750
3
        my_data->main_iDomStatus->setObjectState("cameraLED",STATE::OFF);
751
3
        //printf("w ifie\n");
752
3
    }
753
3
}
754
755
nlohmann::json iDomTOOLS::sendViberMsg(const std::string &msg,
756
                                       const std::string &receiver,
757
                                       const std::string &senderName,
758
                                       const std::string& accessToken,
759
                                       const std::string& url)
760
11
{
761
11
    nlohmann::json jj;
762
11
    std::lock_guard<std::mutex> lock(m_msgMutex);
763
11
    jj = nlohmann::json::parse( m_viber.sendViberMSG(msg,receiver,senderName,accessToken,url));
764
11
    return jj;
765
11
}
766
767
nlohmann::json iDomTOOLS::sendViberPicture(const std::string &msg,
768
                                           const std::string &image,
769
                                           const std::string &receiver,
770
                                           const std::string &senderName,
771
                                           const std::string& accessToken,
772
                                           const std::string& url)
773
25
{
774
25
    nlohmann::json jj;
775
25
    std::lock_guard<std::mutex> lock(m_msgMutex);
776
25
    jj = nlohmann::json::parse(m_viber.sendViberPicture(msg,image,receiver,senderName,accessToken,url));
777
25
    return jj;
778
25
}
779
780
STATE iDomTOOLS::sendViberMsgBool(const std::string &msg,
781
                                  const std::string &receiver,
782
                                  const std::string &senderName,
783
                                  const std::string& accessToken,
784
                                  const std::string& url)
785
2
{
786
2
    nlohmann::json jj = sendViberMsg(msg,receiver,senderName,accessToken,url);
787
2
    STATE ret = STATE::SEND_NOK;
788
2
    if(jj.find("status_message")!= jj.end())
789
2
    {
790
0
        if(jj.at("status_message").get<std::string>() == "ok")
791
0
        {
792
0
            ret = STATE::SEND_OK;
793
0
        }
794
0
    }
795
2
    else
796
2
    {
797
2
        log_file_mutex.mutex_lock();
798
2
        log_file_cout << ERROR << "nie wyslanno wiadomosci viber"<< jj.dump()<< std::endl;
799
2
        log_file_mutex.mutex_unlock();
800
2
    }
801
2
    return ret;
802
2
}
803
804
STATE iDomTOOLS::sendViberPictureBool(const std::string& msg,
805
                                      const std::string& image,
806
                                      const std::string& receiver,
807
                                      const std::string& senderName,
808
                                      const std::string& accessToken,
809
                                      const std::string& url)
810
0
{
811
0
    nlohmann::json jj = sendViberPicture(msg,image,receiver,senderName,accessToken,url);
812
0
    STATE ret = STATE::SEND_NOK;
813
0
    if(jj.at("status_message").get<std::string>() == "ok")
814
0
    {
815
0
        ret = STATE::SEND_OK;
816
0
    }
817
0
    else
818
0
    {
819
0
        log_file_mutex.mutex_lock();
820
0
        log_file_cout << ERROR << "nie wyslanno wiadomosci viber"<< jj.dump()<< std::endl;
821
0
        log_file_mutex.mutex_unlock();
822
0
    }
823
0
    return ret;
824
0
}
825
826
std::string iDomTOOLS::postOnFacebook(const std::string& msg, const std::string& image)
827
2
{
828
2
    std::lock_guard<std::mutex> lock(m_msgMutex);
829
2
    if (image != "NULL"){
830
2
        return m_facebook.postPhotoOnWall(image,msg);
831
2
    }
832
2
833
2
    return m_facebook.postTxtOnWall(msg);
834
2
}
835
836
std::string iDomTOOLS::ledOFF()
837
12
{
838
12
    return useful_F::send_to_arduino(my_data,"LED_STOP:2;");
839
12
}
840
841
std::string iDomTOOLS::ledClear()
842
1
{
843
1
    return useful_F::send_to_arduino(my_data,"LED_CLEAR:2;");
844
1
}
845
846
std::string iDomTOOLS::ledClear(unsigned int from, unsigned int to)
847
13
{
848
13
    LED_Strip ledColor(0,60,0,0,0,"BLACK");
849
13
    useful_F::send_to_arduino(my_data,ledColor.get(from, to));
850
13
    return "Led cleared";
851
13
}
852
853
std::string iDomTOOLS::ledOn(const LED_Strip& ledColor, unsigned int from, unsigned int to)
854
21
{
855
21
    if (my_data->idom_all_state.houseState == STATE::UNLOCK)
856
21
    {
857
3
        return useful_F::send_to_arduino(my_data,ledColor.get(from, to));
858
3
    }
859
21
    else{
860
18
        my_data->myEventHandler.run("LED")->addEvent("LED can not start due to home state: "+
861
18
                                                     stateToString(my_data->idom_all_state.houseState));
862
18
    }
863
21
    return "iDom LOCKED!";
864
21
}
865
866
void iDomTOOLS::checkAlarm()
867
10
{
868
10
    unsigned int fromVol = my_data->alarmTime.fromVolume;
869
10
    unsigned int toVol   = my_data->alarmTime.toVolume;
870
10
    unsigned int radioId = my_data->alarmTime.radioID;
871
10
872
10
    Clock now = Clock::getTime();
873
10
    if (now == my_data->alarmTime.time && my_data->alarmTime.state == STATE::ACTIVE){
874
1
        my_data->alarmTime.state = STATE::WORKING;
875
1
        MPD_volumeSet(my_data, fromVol);
876
1
        MPD_play(my_data,radioId);
877
1
        my_data->main_iDomStatus->setObjectState("alarm",STATE::DEACTIVE);
878
1
    }
879
10
880
10
    if (my_data->alarmTime.state == STATE::WORKING){
881
10
        unsigned int vol = MPD_getVolume(my_data) + 1;
882
10
        if (vol < toVol){
883
9
            MPD_volumeSet(my_data, vol);
884
9
885
9
            if(iDomTOOLS::isItDay() == false){
886
9
                my_data->main_iDomTools->ledOn(my_data->ptr_pilot_led->colorLED[2],fromVol,vol);
887
9
            }
888
9
        }
889
10
        else{
890
1
            my_data->alarmTime.state = STATE::DEACTIVE;
891
1
            if(iDomTOOLS::isItDay() == false){
892
1
                // my_data->main_iDomTools->turnOn433MHzSwitch("ALARM");
893
1
            }
894
1
        }
895
10
    }
896
10
}
897
898
void iDomTOOLS::saveState_iDom()
899
47
{
900
47
    iDom_SAVE_STATE info(my_data->server_settings->saveFilePath);
901
47
    nlohmann::json jsonAlarm;
902
47
    nlohmann::json jsonMPD;
903
47
    nlohmann::json json_iDomLOCK;
904
47
    nlohmann::json json433Mhz;
905
47
    //////////////////// iDom
906
47
    json_iDomLOCK["iDomLock"] = stateToString(my_data->idom_all_state.houseState);
907
47
    //////////////////// alarm
908
47
    jsonAlarm["alarm"] = my_data->main_iDomStatus->getObjectStateString("alarm");
909
47
    jsonAlarm["time"]  = my_data->alarmTime.time.getString();
910
47
    jsonAlarm["fromVolume"] = my_data->alarmTime.fromVolume;
911
47
    jsonAlarm["toVolume"] = my_data->alarmTime.toVolume;
912
47
    jsonAlarm["radioID"] = my_data->alarmTime.radioID;
913
47
    //////////////////// mpd
914
47
    jsonMPD["music"] = my_data->main_iDomStatus->getObjectStateString("music");
915
47
    jsonMPD["speakers"] = my_data->main_iDomStatus->getObjectStateString("speakers");
916
47
    ////////////////// 433Mhz
917
47
    auto switch433vector = my_data->main_REC->getSwitchPointerVector();
918
47
    for (auto v : switch433vector)
919
235
    {
920
235
        v->getName();
921
235
        json433Mhz[v->getName()] = stateToString(v->getState());
922
235
    }
923
47
    ///
924
47
    nlohmann::json json;
925
47
    json["iDom"] = json_iDomLOCK;
926
47
    json["ALARM"] = jsonAlarm;
927
47
    json["MPD"] = jsonMPD;
928
47
    json["433Mhz"] = json433Mhz;
929
47
930
47
    info.write(json);
931
47
#ifdef BT_TEST
932
47
    std::cout << json <<std::endl;
933
47
    std::cout << " saved to " << my_data->server_settings->saveFilePath <<std::endl;
934
47
#endif
935
47
}
936
937
void iDomTOOLS::readState_iDom()
938
2
{
939
2
    try
940
2
    {
941
2
        iDom_SAVE_STATE info(my_data->server_settings->saveFilePath);
942
2
        nlohmann::json jj = info.read();
943
2
#ifdef BT_TEST
944
2
        std::cout << "JSON: " << jj.dump(4) << std::endl;
945
2
#endif
946
2
        nlohmann::json json433MHz = jj.at("433Mhz");
947
2
948
7
        for (nlohmann::json::iterator it = json433MHz.begin(); it != json433MHz.end(); ++it)
949
5
        {
950
5
            if( it.value() == "ON"){
951
0
                my_data->main_iDomTools->turnOn433MHzSwitch(it.key());
952
0
            }
953
5
            else if ( it.value() == "OFF"){
954
0
                my_data->main_iDomTools->turnOff433MHzSwitch(it.key());
955
0
            }
956
5
        }
957
2
        auto iDomLock = jj.at("iDom").at("iDomLock").get<std::string>();
958
2
959
2
        if(iDomLock == "UNLOCK")
960
2
            unlockHome();
961
2
        else if (iDomLock == "LOCK")
962
2
            lockHome();
963
2
964
2
        auto mpdMusic = jj.at("MPD").at("music").get<std::string>();
965
2
        auto mpdSpeakers = jj.at("MPD").at("speakers").get<std::string>();
966
2
967
2
        if(mpdMusic == "PLAY")
968
2
            MPD_play(my_data);
969
2
        else if(mpdMusic == "STOP")
970
1
            MPD_stop();
971
2
        if(mpdSpeakers == "ON")
972
2
            turnOnSpeakers();
973
2
        else if(mpdSpeakers == "OFF")
974
1
            turnOffSpeakers();
975
2
976
2
        auto alarmState = jj.at("ALARM").at("alarm").get<std::string>();
977
2
        auto alarmTime  = jj.at("ALARM").at("time").get<std::string>();
978
2
        my_data->alarmTime.fromVolume = jj.at("ALARM").at("fromVolume").get<int>();
979
2
        my_data->alarmTime.toVolume = jj.at("ALARM").at("toVolume").get<int>();
980
2
        my_data->alarmTime.radioID = jj.at("ALARM").at("radioID").get<int>();
981
2
        my_data->alarmTime.time = Clock(alarmTime);
982
2
983
2
        if (alarmState == "ACTIVE"){
984
1
            my_data->alarmTime.state = STATE::ACTIVE;
985
1
            my_data->main_iDomStatus->setObjectState("alarm", my_data->alarmTime.state);
986
1
            saveState_iDom();
987
1
        }
988
2
    }
989
2
    catch(...)
990
2
    {
991
1
        log_file_mutex.mutex_lock();
992
1
        log_file_cout << ERROR << "nie ma pliku json z stanem iDom"<< std::endl;
993
1
        log_file_mutex.mutex_unlock();
994
1
#ifdef BT_TEST
995
1
        std::cout << "nie ma pliku json z stanem iDom" << std::endl;
996
1
#endif
997
1
    }
998
2
}
999
1000
std::string iDomTOOLS::startKodi_Thread()
1001
4
{
1002
4
    STATE kodiState = my_data->main_iDomStatus->getObjectState("KODI");
1003
4
    if (kodiState == STATE::ACTIVE)
1004
4
        return "kodi already run";
1005
4
1006
4
    return iDOM_THREAD::start_thread("kodi smartTV",useful_F::kodi,my_data);
1007
4
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/test/commandhandler_BT.cpp
Line
Count
Source
1
#include "../commandhandlerrs232.h"
2
#include "../../iDomTools/test/iDomTools_fixture.h"
3
4
class command_handler_rs232_fixture : public iDomTOOLS_ClassTest
5
{
6
public:
7
    command_handler_rs232_fixture()
8
1
    {
9
1
10
1
    }
11
12
protected:
13
    std::unique_ptr<commandHandlerRS232> test_chRS232;
14
    std::vector<std::string> test_v;
15
    void SetUp() final
16
1
    {
17
1
        iDomTOOLS_ClassTest::SetUp();
18
1
        test_chRS232 = std::make_unique<commandHandlerRS232>(&test_my_data);
19
1
    }
20
21
    void TearDown() final
22
1
    {
23
1
        iDomTOOLS_ClassTest::TearDown();
24
1
    }
25
};
26
27
TEST_F(command_handler_rs232_fixture, main)
28
1
{
29
1
    test_v.push_back("ok");
30
1
    auto ret = test_chRS232->run(test_v, &test_my_data);
31
1
    EXPECT_STREQ(ret.c_str(), "\nEND\n");
32
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDomTools/idomtools_mpd.cpp
Line
Count
Source
1
#include "idomtools.h"
2
#include "../blockQueue/blockqueue.h"
3
#include "../functions/functions.h"
4
5
void iDomTOOLS::MPD_play(thread_data* my_data)
6
11
{
7
11
    if(my_data->idom_all_state.houseState == STATE::UNLOCK)
8
11
    {
9
6
        blockQueue _q;
10
6
        _q._add(MPD_COMMAND::PLAY);
11
6
    }
12
11
    else
13
11
    {
14
5
        my_data->myEventHandler.run("MPD")->addEvent("MPD can not start due to home state: "+
15
5
                                                     stateToString(my_data->idom_all_state.houseState));
16
5
    }
17
11
}
18
19
void iDomTOOLS::MPD_stop()
20
13
{
21
13
    blockQueue _q;
22
13
    _q._add(MPD_COMMAND::STOP);
23
13
}
24
25
void iDomTOOLS::MPD_next()
26
2
{
27
2
    blockQueue _q;
28
2
    _q._add(MPD_COMMAND::NEXT);
29
2
}
30
31
void iDomTOOLS::MPD_prev()
32
2
{
33
2
    blockQueue _q;
34
2
    _q._add(MPD_COMMAND::PREV);
35
2
}
36
37
void iDomTOOLS::MPD_pause()
38
5
{
39
5
    blockQueue _q;
40
5
    _q._add(MPD_COMMAND::PAUSE);
41
5
}
42
43
void iDomTOOLS::MPD_volumeUp()
44
2
{
45
2
    blockQueue _q;
46
2
    _q._add(MPD_COMMAND::VOLUP);
47
2
}
48
49
void iDomTOOLS::MPD_volumeDown()
50
2
{
51
2
    blockQueue _q;
52
2
    _q._add(MPD_COMMAND::VOLDOWN);
53
2
}
54
55
void iDomTOOLS::MPD_volumeSet(thread_data *my_data, int vol)
56
12
{
57
12
    my_data->ptr_MPD_info->volume = vol;
58
12
    blockQueue _q;
59
12
    _q._add(MPD_COMMAND::VOLSET);
60
12
}
61
62
void iDomTOOLS::MPD_play(thread_data *my_data, int id)
63
4
{
64
4
    if(my_data->idom_all_state.houseState == STATE::UNLOCK)
65
4
    {
66
2
        my_data->ptr_MPD_info->currentSongID = id;
67
2
        blockQueue _q;
68
2
        _q._add(MPD_COMMAND::PLAY_ID);
69
2
    }
70
4
    else
71
4
    {
72
2
        my_data->myEventHandler.run("MPD")->addEvent("MPD can not start due to home state: "+
73
2
                                                     stateToString(my_data->idom_all_state.houseState));
74
2
    }
75
4
}
76
77
int iDomTOOLS::MPD_getVolume(thread_data *my_data)
78
11
{
79
11
    return my_data->ptr_MPD_info->volume;
80
11
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/command/test/commandhandler_stub.cpp
Line
Count
Source
1
#include "../../src/functions/functions.h"
2
#include "../../src/LCD_c/lcd_c.h"
3
4
//std::string useful_F::send_to_arduino (thread_data *my_data_logic, const std::string& msg){
5
//    return "retunr test ";
6
//}
7
8
5
std::string useful_F::send_to_arduino_clock (thread_data *my_data_logic, std::string msg){
9
5
    return "return test";
10
5
}
11
std::string useful_F::l_send_file(std::string path, std::string find, bool reverse )
12
3
{
13
3
    return "return test in l_send_file()";
14
3
}
15
16
1
std::string LCD_c::getData(){
17
1
    return " data test";
18
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDomTools/idomtools_system.cpp
Line
Count
Source
1
#include "idomtools.h"
2
#include <sys/sysinfo.h>
3
#include <sys/utsname.h>
4
#include <sys/resource.h>
5
#include <sys/time.h>
6
#include <unistd.h>
7
8
std::string iDomTOOLS::getSystemInfo()
9
2
{
10
2
    double load[3];
11
2
    if (getloadavg(load, 3) != -1)
12
2
    {
13
2
#ifdef BT_TEST
14
2
        printf("load average : %f , %f , %f\n", load[0],load[1],load[2]);
15
2
#endif
16
2
    }
17
2
    const double megabyte = 1024 * 1024;
18
2
    struct sysinfo info;
19
2
    sysinfo(&info);
20
2
21
2
    long input_seconds = info.uptime;
22
2
    auto days = input_seconds / 60 / 60 / 24;
23
2
    auto hours = (input_seconds / 60 / 60) % 24;
24
2
    auto minutes = (input_seconds / 60) % 60;
25
2
    auto seconds = input_seconds % 60;
26
2
27
2
    std::stringstream ret;
28
2
    ret << "System uptime: " << days <<" day " << hours
29
2
        << " hours " << minutes << " minutes "
30
2
        << seconds << " seconds " << std::endl << "Load: "
31
2
        << (info.loads[0]/65536) << "% - 1 min, " <<(info.loads[1]/65536)
32
2
        << "% - 5 min, "<<(info.loads[2]/65536) << "% - 15 min." << std::endl
33
2
        << "process count : " << info.procs << std::endl
34
2
        << "total RAM   : "<< (info.totalram / megabyte)<< "MB" << std::endl
35
2
        << "free RAM   : " << (info.freeram / megabyte) << "MB" << std::endl;
36
2
37
2
    return ret.str();
38
2
}
39
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/files_tree/files_tree.cpp
Line
Count
Source (jump to first uncovered line)
1
#include "files_tree.h"
2
3
bool comper (const movie_database & a , const movie_database& b)
4
212
{
5
212
    return a.files_name < b.files_name;
6
212
}
7
files_tree::files_tree (const std::string& path, LCD_c *mainLCD_PTR):database_path(path),w_serial( "([Ss]\\d{1,3}[Ee]\\d{1,3})")
8
9
12
{
10
12
    //database_path = path;
11
12
    mainLCD = mainLCD_PTR;
12
12
    //tree_stack.push(database_path);
13
12
    i_stack.push(0);
14
12
    i = 0;
15
12
    get_list(database_path);
16
12
}
17
bool files_tree::is_file() const
18
3
{
19
3
    return movie_database_vector[i].is_file;
20
3
}
21
22
void files_tree::next()
23
3
{   
24
3
    ++i;
25
3
    ////std::cout << " dodaje " << i << std::endl;
26
3
    if (get_vector_size() == i ){
27
1
        i=0;
28
1
    }
29
3
}
30
31
void files_tree::previous()
32
5
{
33
5
    --i;
34
5
    ////std::cout << " odejmuje " << i << std::endl;
35
5
36
5
    if ( i <0 )
37
2
    {
38
2
        i=get_vector_size()-1;
39
2
    }
40
5
}
41
42
int files_tree::get_vector_size () const
43
5
{
44
5
    return movie_database_vector.size();
45
5
}
46
void files_tree::vector_clear ()
47
14
{
48
14
    movie_database_vector.clear();
49
14
}
50
int files_tree::get_i()
51
1
{ if (i_stack.size() >1 ) {
52
1
        int i = i_stack.top();
53
1
        i_stack.pop();
54
1
        return i;
55
1
    }
56
0
    else
57
0
        return 0;
58
1
}
59
60
void files_tree::enter_dir()
61
1
{
62
1
    i_stack.push(i); // wpisuje na stos kolejna wersje licznika i
63
1
64
1
    if (movie_database_vector[i].is_file == false) {
65
1
        get_list (movie_database_vector[i].path);
66
1
        i=0;
67
1
    }
68
1
69
1
}
70
void files_tree::enter_dir(const std::string& path)
71
0
{ //tree_stack.push(path);
72
0
    get_list (path);
73
0
}
74
75
void files_tree::back_dir()
76
1
{
77
1
    if ( tree_stack.size() >1 ) {
78
1
        tree_stack.pop();
79
1
        std::string path = tree_stack.top();
80
1
        tree_stack.pop();
81
1
        i=get_i();
82
1
        get_list (path);
83
1
        return;
84
1
    }
85
0
    i=get_i();
86
0
87
0
    ////std::cout << " III ma teraz : " << i << std::endl;
88
0
    get_list (database_path);
89
0
    return;
90
0
}
91
92
std::string files_tree::show_list()
93
24
{
94
24
    //std::cout << "iteracja!!!!!!!!!!!!!!!!!!!!!!: " << i <<"rozmiar vectora : " << get_vector_size() << std::endl;
95
24
    if (movie_database_vector[i].is_file == true ) {
96
12
        //std::cout << "wypisuje sciezke pliku " << movie_database_vector[i].path <<" | " <<movie_database_vector[i].files_name.substr(0,16)<< std::endl;
97
12
98
12
        mainLCD->printString(true,0,0,movie_database_vector[i].files_name.substr(0,16));
99
12
        if( regex_search(movie_database_vector[i].path,result,w_serial) )
100
12
        {
101
12
            mainLCD->printString(false,10,1,movie_database_vector[i].files_name.substr( movie_database_vector[i].files_name.size()-4,movie_database_vector[i].files_name.size()));
102
12
            mainLCD->printString(false, 1,1,result[0]);
103
12
        }
104
0
        else
105
0
        {
106
0
            mainLCD->printString(false,10,1,movie_database_vector[i].files_name.substr( movie_database_vector[i].files_name.size()-4,movie_database_vector[i].files_name.size()));
107
0
        }
108
12
    }
109
12
    else {
110
12
        mainLCD->printString(true,0,0,movie_database_vector[i].files_name+"/");
111
12
    }
112
24
    return movie_database_vector[i].path;
113
24
}
114
115
14
void files_tree::get_list(std::string path) {
116
14
    tree_stack.push(path);
117
14
    vector_clear(); // czyscimy vector
118
14
    std::string path2 =path;
119
14
    std::string v_path ,tmp_string;
120
14
121
14
    if(sciezka = opendir( path.c_str() )) {
122
14
123
82
        while(( plik = readdir( sciezka ) ) )
124
68
        {
125
68
            path2 =path;
126
68
            if (static_cast<int>(plik->d_type) == 4 /*&& strcmp( plik->d_name, "..") && strcmp( plik->d_name, ".")*/)
127
41
            {
128
41
                temp.is_file=false;
129
41
            }
130
27
            else //if ( (int)plik->d_type == 8 && strcmp( plik->d_name, "..") && strcmp( plik->d_name, "."))
131
27
            {
132
27
                temp.is_file=true;
133
27
            }
134
68
135
68
            v_path= path2;
136
68
            v_path+="/";
137
68
            tmp_string.assign(plik->d_name);
138
68
            v_path+=tmp_string;
139
68
            temp.path =v_path;
140
68
            temp.files_name.assign(plik->d_name);
141
68
            movie_database_vector.push_back(temp);
142
68
        }// end while
143
14
        sort(movie_database_vector.begin(),movie_database_vector.end(), comper);
144
14
        closedir( sciezka );
145
14
    }
146
14
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDomTools/lightning.cpp
Line
Count
Source
1
#include "lightning.h"
2
3
LIGHTNING::LIGHTNING()
4
392
{
5
392
    puts("LIGHTNING::LIGHTNING()");
6
392
}
7
8
LIGHTNING::~LIGHTNING()
9
392
{
10
392
    puts("LIGHTNING::~LIGHTNING()");
11
392
}
12
13
CARDINAL_DIRECTIONS::ALARM_INFO LIGHTNING::lightningAlert(nlohmann::json jj)
14
13
{
15
13
    CARDINAL_DIRECTIONS::ALARM_INFO data;
16
13
    nlohmann::json i;
17
13
18
13
#ifdef BT_TEST
19
13
    std::cout <<"\n\n data all " << i.dump(4) <<" size:"<< i.size() <<std::endl;
20
13
#endif
21
13
    if (jj.find("response") != jj.end())
22
13
    {
23
12
        i = jj.at("response").get<nlohmann::json>();
24
12
    }
25
13
    else
26
13
    {
27
1
        std::cout << " zly JSON " <<std::endl;
28
1
        return data;
29
1
    }
30
13
31
13
    auto _size = i.size();
32
12
    if (_size == 0)
33
12
    {
34
4
        data.riseAlarm = false;
35
4
        return data;
36
4
    }
37
12
    STATISTIC<int> ageAver(_size);
38
8
    STATISTIC<double> distanceKmAver(_size);
39
8
    STATISTIC<int> bearingAver(_size);
40
146
    for (auto j : i){
41
146
#ifdef BT_TEST
42
146
   //     std::cout <<"\n distance " << j.at("relativeTo").at("bearingENG").get<std::string>() << std::endl;
43
146
   //     std::cout <<"distance " << j.at("relativeTo").at("distanceKM").get<double>() << std::endl;
44
146
   //     std::cout <<"timestamp " << j.at("age").get<int>() << std::endl;
45
146
#endif
46
146
        ageAver.push_back(j.at("age").get<int>());
47
146
        distanceKmAver.push_back(j.at("relativeTo").at("distanceKM").get<double>());
48
146
        bearingAver.push_back(static_cast<int>(CARDINAL_DIRECTIONS::stringToCardinalDirectionsEnum(
49
146
                                                   j.at("relativeTo").at("bearingENG").get<std::string>()))
50
146
                              );
51
146
    }
52
8
    data.bearingENG = static_cast<CARDINAL_DIRECTIONS::CARDINAL_DIRECTIONS_ENUM>(bearingAver.mode());
53
8
    data.distance = distanceKmAver.average();
54
8
    data.timestamp = ageAver.median();
55
8
56
8
    data.data.str(std::string());
57
8
    data.data << "ilość uderzeń: "<< _size << "\\n";
58
8
    data.data << "średni czas upłynięty od ostatniego uderzenia pioruna: "<< data.timestamp << " sek \\n";
59
8
    data.data << "średnia odległość ostatniego uderzenia pieruna: "<< data.distance <<" km \\n ";
60
8
    data.data << "kierunek uderzeń piorunów: " << CARDINAL_DIRECTIONS::cardinalDirectionsEnumToHuman(data.bearingENG);
61
8
62
8
    if(i.size() > 0){
63
8
        // std::cout << "jest size: " << i.size()<<std::endl;
64
8
        data.riseAlarm = true;
65
8
    }
66
8
67
8
    return data;
68
12
}
69
70
bool LIGHTNING::checkLightningAlert(CARDINAL_DIRECTIONS::ALARM_INFO *info)
71
15
{
72
15
#ifdef BT_TEST
73
15
    std::cout << "LIGHTNING::checkLightningAlert() bool "<< info->riseAlarm <<" local " << alarmState << std::endl
74
15
              << " distance " << info->distance << std::endl;
75
15
#endif
76
15
    if(info->riseAlarm == false && alarmState == false){
77
4
#ifdef BT_TEST
78
4
        std::cout << "(info->riseAlarm == false || alarmState == false)"<<std::endl;
79
4
#endif
80
4
        return false;
81
4
    }
82
15
    if(info->riseAlarm == false && alarmState == true){
83
2
#ifdef BT_TEST
84
2
        std::cout << "(info->riseAlarm == false || alarmState == true)"<<std::endl;
85
2
#endif
86
2
        alarmState = false;
87
2
        return false;
88
2
    }
89
11
    if(info->riseAlarm == true && alarmState == false){
90
5
91
5
#ifdef BT_TEST
92
5
        std::cout << "(info->riseAlarm == true || alarmState == false)"<<std::endl;
93
5
#endif
94
5
        alarmState = true;
95
5
        lightningTime = Clock::getTime();
96
5
        oldDistance = info->distance;
97
5
        std::cout << " w true oldDistance: "<< oldDistance <<std::endl;
98
5
        return true;
99
5
    }
100
9
101
9
#ifdef BT_TEST
102
9
    std::cout << "checkLightningAlert() - dystans"<<std::endl;
103
4
    std::cout << "Dystans: " <<info->distance << " oldDistance: "<< oldDistance <<std::endl;
104
4
#endif
105
4
    if(oldDistance > info->distance)
106
4
    {
107
1
108
1
        oldDistance = info->distance;
109
1
        return true;
110
1
    }
111
4
    else
112
4
    {
113
3
        oldDistance = info->distance;
114
3
    }
115
4
    ////////////////clear
116
4
    //oldDistance = 0.0;
117
4
    return false;
118
4
}
119
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/functions/functions2.cpp
Line
Count
Source (jump to first uncovered line)
1
#include <iostream>
2
#include <fstream>
3
#include <regex>
4
#include <iterator>
5
#include <vector>
6
7
#include "functions.h"
8
#include "../thread_functions/iDom_thread.h"
9
10
23
std::vector<std::string> useful_F::split(const std::string& s, char separator ){
11
23
    std::vector<std::string> output;
12
23
    std::string::size_type prev_pos = 0, pos = 0;
13
23
14
53
    while((pos = s.find(separator, pos)) != std::string::npos)
15
30
    {
16
30
        std::string substring( s.substr(prev_pos, pos-prev_pos) );
17
30
        output.push_back(substring);
18
30
        prev_pos = ++pos;
19
30
    }
20
23
    try
21
23
    {
22
23
        output.push_back(s.substr(prev_pos, pos-prev_pos)); // Last word
23
23
    }
24
23
    catch (...)
25
23
    {
26
0
        log_file_mutex.mutex_lock();
27
0
        log_file_cout << CRITICAL << "wyjatek substr() w useful_F::split() !!!!!!"<< std::endl;
28
0
        log_file_mutex.mutex_unlock();
29
0
    }
30
23
    return output;
31
23
}
32
thread_data* useful_F::myStaticData = std::nullptr_t();
33
void useful_F::setStaticData(thread_data *my_dataPtr)
34
1
{
35
1
    myStaticData = my_dataPtr;
36
1
}
37
38
5
void useful_F::tokenizer ( std::vector <std::string> &command, std::string separator, std::string &text){
39
5
    std::string temp;
40
5
41
5
    for(char n: text)
42
44
    { // the initializer may be an array
43
44
        bool is_sep = false;
44
44
        for(char m: separator)
45
119
        {
46
119
            if (n == m)
47
5
                is_sep = true;
48
119
        }
49
44
        if (is_sep == false)
50
39
            temp += n;
51
5
        else
52
5
        {
53
5
            if (!temp.empty())
54
5
            {
55
5
                command.push_back( temp);
56
5
                temp = "";
57
5
            }
58
5
        }
59
44
    }
60
5
    if (!temp.empty())
61
3
        command.push_back(temp);
62
5
63
5
    if (command.size() == 0)
64
2
        throw std::string("command empty");
65
3
}
66
67
////// watek sleeper
68
void useful_F::sleeper_mpd (thread_data *my_data, const std::string& threadName)
69
3
{
70
3
    unsigned int t = 60/my_data->sleeper;
71
3
    unsigned int k = 0;
72
3
73
16
    for (; my_data->sleeper >0; my_data->sleeper-- )
74
13
    {
75
13
        useful_F::sleep(60);
76
13
        k += t;
77
13
        my_data->main_iDomTools->ledClear(0,k);
78
13
    }
79
3
    my_data->main_iDomTools->ledOFF();
80
3
    my_data->main_iDomTools->MPD_stop();
81
3
    my_data->main_iDomTools->turnOff433MHzSwitch("listwa");
82
3
83
3
    log_file_mutex.mutex_lock();
84
3
    log_file_cout << INFO<< "zaczynam procedure konca watku " << threadName << std::endl;
85
3
    log_file_mutex.mutex_unlock();
86
3
87
3
    iDOM_THREAD::stop_thread(threadName,my_data);
88
3
89
3
    log_file_mutex.mutex_lock();
90
3
    log_file_cout << INFO<< "koniec watku SLEEP_MPD" << std::endl;
91
3
    log_file_mutex.mutex_unlock();
92
3
}
93
94
///////////////////////////////////////////////////////////////////////////////////////////////////// watek kodi
95
void useful_F::kodi (thread_data *my_data, const std::string& threadName)
96
2
{
97
2
    log_file_mutex.mutex_lock();
98
2
    log_file_cout << INFO<< "start wątku "<<threadName << std::endl;
99
2
    log_file_mutex.mutex_unlock();
100
2
101
2
    my_data->mainLCD->set_print_song_state(100);
102
2
    my_data->mainLCD->printString(false,2,1,"  KODI");
103
2
104
2
    my_data->main_iDomStatus->setObjectState("KODI",STATE::ACTIVE);
105
2
    //status mpd
106
2
    STATE musicState = my_data->main_iDomStatus->getObjectState("music");
107
2
    // status glosnikow
108
2
    STATE speakersState = my_data->main_iDomStatus->getObjectState("speakers");
109
2
110
2
    if (musicState != STATE::STOP)
111
2
        my_data->main_iDomTools->MPD_pause();
112
2
    if (speakersState != STATE::ON)
113
1
        my_data->main_iDomTools->turnOnSpeakers();
114
2
    //system
115
2
116
2
    int ret = useful_F::runLinuxCommand("runuser -u pi kodi");
117
2
118
2
    if(ret != 0)
119
0
    {
120
0
        log_file_mutex.mutex_lock();
121
0
        log_file_cout << CRITICAL<< "kodi zamkniete z błędem "<<ret << std::endl;
122
0
        log_file_mutex.mutex_unlock();
123
0
    }
124
2
    //przywracanie danych
125
2
126
2
    if(musicState == STATE::PLAY)
127
1
        my_data->main_iDomTools->MPD_play(my_data);
128
1
    else
129
1
        my_data->main_iDomTools->turnOffSpeakers();
130
2
    //koniec
131
2
132
2
    my_data->main_iDomStatus->setObjectState("KODI",STATE::DEACTIVE);
133
2
    my_data->mainLCD->set_print_song_state(0);
134
2
    iDOM_THREAD::stop_thread("kodi smartTV",my_data);
135
2
}
136
std::string useful_F::RSHash(const std::string& data, unsigned int b, unsigned int a)
137
4
{
138
4
    time_t act_time;
139
4
    struct tm * act_date;
140
4
    time(&act_time);
141
4
    act_date = localtime(&act_time);
142
4
    char buffer[10];
143
4
    strftime(buffer,10,"%M%H%w",act_date);
144
4
    std::string str(buffer);
145
4
    str+=data;
146
4
    unsigned int hash = 0;
147
4
148
56
    for(std::size_t i = 0; i < str.length(); i++)
149
52
    {
150
52
        hash = hash * a + str[i];
151
52
        a = a * b;
152
52
    }
153
4
    return std::to_string((hash & 0x7FFFFFFF));
154
4
}
155
156
int useful_F::findFreeThreadSlot(std::array<Thread_array_struc, iDomConst::MAX_CONNECTION> *array)
157
5
{
158
24
    for (std::size_t i = 0; i< array->size(); ++i)
159
23
    {
160
23
        if (array->at(i).thread_socket == 0)
161
4
            return static_cast<int>(i);
162
23
    }
163
5
    puts("return -1");
164
1
    return -1;
165
5
}
166
167
std::string useful_F::sek_to_uptime(long long secy )
168
2
{
169
2
    const int min = 60; //s
170
2
    const int houry = 3600; //s
171
2
    const int day = 86400; //s
172
2
    int number_day, number_hour, number_min, number_sec;
173
2
    int temp1, temp2, temp3;
174
2
    number_day = secy / day;
175
2
    std::stringstream text;
176
2
    text << "\n" << number_day << " day ";
177
2
    temp1 = secy % day;
178
2
    number_hour = temp1 / houry;
179
2
    text << number_hour << " hours ";
180
2
    temp2 = temp1 % houry;
181
2
    number_min = temp2 / min;
182
2
    text << number_min << " minutes ";
183
2
    temp3 = temp2 % min;
184
2
    number_sec = temp3;
185
2
    text << number_sec << " seconds";
186
2
    return text.str();
187
2
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDomTools/lightning.h
Line
Count
Source (jump to first uncovered line)
1
#ifndef LIGHTNING_H
2
#define LIGHTNING_H
3
#include <iostream>
4
5
#include "../../libs/Statistic/statistic.h"
6
#include "../../libs/useful/useful.h"
7
8
#include "idomtools_useful.h"
9
#include "json.hpp"
10
11
class CARDINAL_DIRECTIONS{
12
public:
13
    enum class CARDINAL_DIRECTIONS_ENUM{
14
        /*
15
           N
16
        NNW NNE
17
      NW       NE
18
   WNW         ENE
19
 W            E
20
   WSW       ESE
21
      SW     SE
22
        SSW  SSE
23
           S
24
    */
25
26
        N = 1,NNE,NE,ENE,E,ESE,SE,SSE,S,SSW,SW,WSW,W,WNW,NW,NNW,ERROR
27
    };
28
    static CARDINAL_DIRECTIONS_ENUM stringToCardinalDirectionsEnum(std::string s){
29
        if (s == "N")      return CARDINAL_DIRECTIONS_ENUM::N;
30
        else if (s == "NNE")    return CARDINAL_DIRECTIONS_ENUM::NNE;
31
        else if (s == "NE")     return CARDINAL_DIRECTIONS_ENUM::NE;
32
        else if (s == "ENE")    return CARDINAL_DIRECTIONS_ENUM::ENE;
33
        else if (s == "E")      return CARDINAL_DIRECTIONS_ENUM::E;
34
        else if (s == "ESE")    return CARDINAL_DIRECTIONS_ENUM::ESE;
35
        else if (s == "SE")     return CARDINAL_DIRECTIONS_ENUM::SE;
36
        else if (s == "SSE")    return CARDINAL_DIRECTIONS_ENUM::SSE;
37
        else if (s == "S")      return CARDINAL_DIRECTIONS_ENUM::S;
38
        else if (s == "SSW")    return CARDINAL_DIRECTIONS_ENUM::SSW;
39
        else if (s == "SW")     return CARDINAL_DIRECTIONS_ENUM::SW;
40
        else if (s == "WSW")    return CARDINAL_DIRECTIONS_ENUM::WSW;
41
        else if (s == "W")      return CARDINAL_DIRECTIONS_ENUM::W;
42
        else if (s == "WNW")    return CARDINAL_DIRECTIONS_ENUM::WNW;
43
        else if (s == "NW")     return CARDINAL_DIRECTIONS_ENUM::NW;
44
        else if (s == "NNW")    return CARDINAL_DIRECTIONS_ENUM::NNW;
45
        else                    return CARDINAL_DIRECTIONS_ENUM::ERROR;
46
    }
47
48
    static std::string cardinalDirectionsEnumToString(CARDINAL_DIRECTIONS_ENUM e){
49
        switch (e){
50
        case CARDINAL_DIRECTIONS_ENUM::N:
51
            return "N";
52
        case CARDINAL_DIRECTIONS_ENUM::NNE:
53
            return "NNE";
54
        case CARDINAL_DIRECTIONS_ENUM:: NE:
55
            return "NE";
56
        case CARDINAL_DIRECTIONS_ENUM::ENE:
57
            return "ENE";
58
        case CARDINAL_DIRECTIONS_ENUM::E:
59
            return "E";
60
        case CARDINAL_DIRECTIONS_ENUM::ESE:
61
            return "ESE";
62
        case CARDINAL_DIRECTIONS_ENUM::SE:
63
            return "SE";
64
        case CARDINAL_DIRECTIONS_ENUM::SSE:
65
            return "SSE";
66
        case CARDINAL_DIRECTIONS_ENUM::S:
67
            return "S";
68
        case CARDINAL_DIRECTIONS_ENUM::SSW:
69
            return "SSW";
70
        case CARDINAL_DIRECTIONS_ENUM::SW:
71
            return "SW";
72
        case CARDINAL_DIRECTIONS_ENUM::WSW:
73
            return "WSW";
74
        case CARDINAL_DIRECTIONS_ENUM::W:
75
            return "W";
76
        case CARDINAL_DIRECTIONS_ENUM::WNW:
77
            return "WNW";
78
        case CARDINAL_DIRECTIONS_ENUM::NW:
79
            return "NW";
80
        case CARDINAL_DIRECTIONS_ENUM::NNW:
81
            return "NNW";
82
        default:
83
            return "UNKNOWN DIRECTION";
84
        }
85
    }
86
8
    static std::string cardinalDirectionsEnumToHuman(CARDINAL_DIRECTIONS_ENUM e){
87
8
        switch (e){
88
0
        case CARDINAL_DIRECTIONS_ENUM::N:
89
0
            return "północ";
90
0
        case CARDINAL_DIRECTIONS_ENUM::NNE:
91
0
            return "północ - północny wschód";
92
0
        case CARDINAL_DIRECTIONS_ENUM:: NE:
93
0
            return "północny wschód";
94
6
        case CARDINAL_DIRECTIONS_ENUM::ENE:
95
6
            return "wschód - północny wschód";
96
0
        case CARDINAL_DIRECTIONS_ENUM::E:
97
0
            return "wschód";
98
0
        case CARDINAL_DIRECTIONS_ENUM::ESE:
99
0
            return "wschód - południowy wschód";
100
0
        case CARDINAL_DIRECTIONS_ENUM::SE:
101
0
            return "południowy wschód";
102
0
        case CARDINAL_DIRECTIONS_ENUM::SSE:
103
0
            return "południe - południowy wschód";
104
0
        case CARDINAL_DIRECTIONS_ENUM::S:
105
0
            return "południe";
106
0
        case CARDINAL_DIRECTIONS_ENUM::SSW:
107
0
            return "południe - południowy zachów";
108
0
        case CARDINAL_DIRECTIONS_ENUM::SW:
109
0
            return "południowy zachów";
110
2
        case CARDINAL_DIRECTIONS_ENUM::WSW:
111
2
            return "zachód - południowy zachów";
112
0
        case CARDINAL_DIRECTIONS_ENUM::W:
113
0
            return "zachód";
114
0
        case CARDINAL_DIRECTIONS_ENUM::WNW:
115
0
            return "zachód - północny zachód";
116
0
        case CARDINAL_DIRECTIONS_ENUM::NW:
117
0
            return "północny zachód";
118
0
        case CARDINAL_DIRECTIONS_ENUM::NNW:
119
0
            return "północ - północny zachód";
120
0
        default:
121
0
            return "UNKNOWN DIRECTION";
122
0
        }
123
8
    }
124
    struct ALARM_INFO{
125
        ALARM_INFO():
126
            riseAlarm(false),
127
            timestamp(0),
128
            distance(0.0),
129
            bearingENG(CARDINAL_DIRECTIONS::CARDINAL_DIRECTIONS_ENUM::ERROR)
130
        {
131
            data << "NULL";
132
        }
133
        ALARM_INFO(const ALARM_INFO &s):
134
            riseAlarm(s.riseAlarm),
135
            data(s.data.str()),
136
            timestamp(s.timestamp),
137
            distance(s.distance),
138
            bearingENG(s.bearingENG)
139
4
        {
140
4
        }
141
        ALARM_INFO& operator = (const ALARM_INFO& s)
142
        {
143
            this->data.str(std::string());
144
            this->riseAlarm = s.riseAlarm;
145
            this->data << s.data.str();
146
            this->timestamp = s.timestamp;
147
            this->distance = s.distance;
148
            this->bearingENG = s.bearingENG;
149
            return *this;
150
        }
151
152
        bool riseAlarm;
153
        std::stringstream data;
154
        unsigned int timestamp; //second
155
        double distance; //km
156
        CARDINAL_DIRECTIONS::CARDINAL_DIRECTIONS_ENUM bearingENG;
157
    };
158
};
159
160
class LIGHTNING
161
{
162
public:
163
    LIGHTNING();
164
    ~LIGHTNING();
165
    CARDINAL_DIRECTIONS::ALARM_INFO lightningAlert(nlohmann::json jj);
166
    bool checkLightningAlert(CARDINAL_DIRECTIONS::ALARM_INFO* info);
167
private:
168
    bool alarmState = false;
169
    Clock lightningTime;
170
    double oldDistance = 0.0;
171
};
172
173
#endif // LIGHTNING_H
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/functions/tests/functions_BT.cpp
Line
Count
Source
1
#include <gtest/gtest.h>
2
#include "../functions.h"
3
#include "../../RADIO_433_eq/radio_433_eq.h"
4
#include "../../iDomTools/test/iDomTools_fixture.h"
5
6
class functions_fixture : public iDomTOOLS_ClassTest{
7
8
};
9
10
void useful_F::sleep(int sec)
11
25
{
12
25
    std::cout << "sleep() sec: " << sec <<std::endl;
13
25
}
14
15
TEST(functions_, tokenizer)
16
1
{
17
1
     std::string test_msg = "one=two three";
18
1
     std::vector<std::string> test_v;
19
1
20
1
     EXPECT_EQ(test_v.size(), 0);
21
1
     useful_F::tokenizer(test_v,"= ",test_msg);
22
1
23
1
     EXPECT_EQ(test_v.size(),3);
24
1
     EXPECT_STREQ(test_v.at(2).c_str(),"three");
25
1
}
26
27
TEST(functions_, sekToUptime)
28
1
{
29
1
    EXPECT_STREQ(useful_F::sek_to_uptime(34534).c_str(),"\n0 day 9 hours 35 minutes 34 seconds");
30
1
}
31
32
TEST(functions_, tokenizerEmpty)
33
1
{
34
1
     std::string test_msg = "";
35
1
     std::vector<std::string> test_v;
36
1
37
1
     EXPECT_EQ(test_v.size(), 0);
38
1
     EXPECT_THROW(useful_F::tokenizer(test_v,"= ",test_msg),std::string);
39
1
}
40
41
TEST(functions_, removeHtmlTag)
42
1
{
43
1
     std::string test_msg = "<html>test</html>";
44
1
     std::string test_pure_str = useful_F_libs::removeHtmlTag(test_msg);
45
1
46
1
     EXPECT_STREQ(test_pure_str.c_str(),"test");
47
1
}
48
49
TEST(functions_, repalceAll)
50
1
{
51
1
     std::string test_msg = "one two three";
52
1
     std::string test_pure_str = useful_F_libs::replaceAll(test_msg,"two","zero");
53
1
54
1
     EXPECT_STREQ(test_pure_str.c_str(),"one zero three");
55
1
}
56
57
TEST(functions_, split)
58
1
{
59
1
    std::string test_msg = "one two three";
60
1
    std::vector<std::string> test_v;
61
1
62
1
    EXPECT_EQ(test_v.size(), 0);
63
1
    test_v = useful_F::split(test_msg,' ');
64
1
65
1
    EXPECT_EQ(test_v.size(),3);
66
1
    EXPECT_STREQ(test_v.at(2).c_str(),"three");
67
1
}
68
69
TEST(functions_, RSHash)
70
1
{
71
1
    std::string msg = "test msg";
72
1
    std::string s1  = useful_F::RSHash(msg, 33, 44);
73
1
    std::string s2  = useful_F::RSHash(msg, 33 ,44);
74
1
    EXPECT_STREQ(s1.c_str(), s2.c_str());
75
1
76
1
    s1 = useful_F::RSHash(msg, 35, 44);
77
1
    s2 = useful_F::RSHash(msg, 33 ,44);
78
1
    EXPECT_STRNE(s1.c_str(), s2.c_str());
79
1
}
80
81
TEST_F(functions_fixture, setStaticData)
82
1
{
83
1
    test_my_data.sleeper = 99;
84
1
    EXPECT_EQ( useful_F::myStaticData->sleeper, 99 );
85
1
    thread_data test_my_data2;
86
1
    test_my_data2.sleeper = 88;
87
1
    EXPECT_EQ( test_my_data2.sleeper, 88 );
88
1
    EXPECT_EQ( useful_F::myStaticData->sleeper, 99 );
89
1
    useful_F::setStaticData(&test_my_data2);
90
1
    EXPECT_EQ( useful_F::myStaticData->sleeper, 88 );
91
1
}
92
93
TEST_F(functions_fixture, sleepThread)
94
1
{
95
1
    std::array <Thread_array_struc,10> test_THRARRSTR;
96
1
    test_my_data.main_THREAD_arr = &test_THRARRSTR;
97
1
98
1
    MPD_info test_ptr_MPD;
99
1
    test_ptr_MPD.volume = 3;
100
1
    test_my_data.ptr_MPD_info = &test_ptr_MPD;
101
1
102
1
   // RADIO_EQ_CONTAINER_STUB test_rec(&test_my_data);
103
1
    std::shared_ptr<RADIO_EQ_CONTAINER> test_rec = std::make_shared<RADIO_EQ_CONTAINER>(&test_my_data);
104
1
    test_rec->loadConfig(test_server_set.radio433MHzConfigFile);
105
1
    test_my_data.main_REC = (test_rec);
106
1
    test_my_data.alarmTime.time = Clock::getTime();
107
1
    test_my_data.alarmTime.state = STATE::ACTIVE;
108
1
109
1
    test_my_data.sleeper = 10;
110
1
111
1
    blockQueue test_q;
112
1
    test_q._clearAll();
113
1
    EXPECT_EQ(test_q._size(),0);
114
1
    useful_F::sleeper_mpd(&test_my_data,"test sleep");
115
1
    EXPECT_EQ(test_q._size(),1);
116
2
    EXPECT_EQ(test_q._get(), MPD_COMMAND::STOP) << "NIE ZATRZYMANO MUZYKI :(";
117
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/libs/useful/useful.h
Line
Count
Source
1
#ifndef Iusefull_H
2
#define Iusefull_H
3
4
#include <iostream>
5
#include <string>
6
#include <vector>
7
#include <ostream>
8
#include <chrono>
9
#include <sstream>
10
#include <stdio.h>
11
#include <stdlib.h>
12
#include <iomanip>
13
#ifndef ANDROID
14
#include "json.hpp"
15
#endif
16
17
std::vector<std::string> split_string(const std::string& s, char separator );
18
19
class useful_F_libs {
20
public:
21
    static  void write_to_mkfifo(const std::string& path, const std::string &msg);
22
    static  std::string read_from_mkfifo(const std::string &path);
23
    static size_t  WriteCallback(void *contents, size_t size, size_t nmemb, void *userp);
24
    static std::string find_tag (const std::string &temp);
25
    //////////////////// HTTP req //////////////////////////
26
    static std::string httpPost(const std::string &url, int timeoutSeconds);
27
    static std::string httpPost(const std::string &url);
28
    static void downloadFile(const std::string &url, const std::string &path, int timeoutSeconds);
29
    static std::string replaceAll(std::string str, const std::string& from, const std::string& to);
30
    static std::string removeHtmlTag(std::string &data);
31
    /////////////////////  JSON ////////////////////////////
32
33
#ifndef ANDROID
34
    static nlohmann::json getJson(const std::string &url);
35
#endif
36
};
37
namespace std
38
{
39
40
#ifdef ANDROID
41
template <typename T>
42
int stoi(T s){
43
    return atoi(s.c_str());
44
}
45
#endif
46
47
template <typename T>
48
std::string to_string(T value)
49
2
{
50
2
    std::ostringstream os;
51
2
    os << value;
52
2
    return os.str();
53
2
}
54
} // namespace std
55
56
template <typename T>
57
std::string to_string_with_precision(const T a_value, const int n = 4)
58
{
59
    std::ostringstream out;
60
    out << std::setprecision(n) << a_value;
61
    return out.str();
62
}
63
64
struct Clock{
65
private:
66
    std::time_t m_time;
67
#ifdef BT_TEST
68
    static unsigned int m_BT_H;
69
    static unsigned int m_BT_M;
70
#endif
71
public:
72
    unsigned int m_h = 0;
73
    unsigned int m_min = 0;
74
    Clock () {}
75
    Clock(std::string t){
76
        std::vector<std::string> vt = split_string(t,':');
77
        int h = std::stoi(vt.at(0));
78
        int m = std::stoi(vt.at(1));
79
        set(static_cast <unsigned int>(h),static_cast <unsigned int>(m));
80
    }
81
82
    Clock(unsigned int h, unsigned int m) {
83
        set(h,m);
84
    }
85
    /////////////////////////////////////////////////////////////////////////////////////
86
    void set(unsigned int h, unsigned int m){
87
        if (h<24 && m <60){
88
            this->m_h = h;
89
            this->m_min = m;
90
        }
91
        else {
92
            throw 0;
93
        }
94
    }
95
96
    /////////////////////////////////////////////////////////////////////////////////////
97
    const std::string getString(){
98
        std::stringstream ret;
99
        if (m_h < 10) {
100
            ret << "0";
101
        }
102
        ret << m_h;
103
        ret << ":";
104
        if (m_min < 10) {
105
            ret << "0";
106
        }
107
        ret << m_min;
108
        return ret.str();
109
    }
110
    /////////////////////////////////////////////////////////////////////////////////////
111
    bool operator == (const Clock & c){
112
        if ((this->m_h == c.m_h) && (this->m_min == c.m_min)){
113
            return true;
114
        }
115
        else{
116
            return false;
117
        }
118
    }
119
    /////////////////////////////////////////////////////////////////////////////////////
120
    bool operator != (const Clock & c){
121
        if ((this->m_h != c.m_h) || (this->m_min != c.m_min)){
122
            return true;
123
        }
124
        else{
125
            return false;
126
        }
127
    }
128
    /////////////////////////////////////////////////////////////////////////////////////
129
    friend std::ostream & operator<< (std::ostream &w ,  Clock &c) {
130
        return w << c.getString();
131
    }
132
    /////////////////////////////////////////////////////////////////////////////////////
133
    bool operator < (const Clock& c){
134
        if (this->m_h < c.m_h){
135
            return true;
136
        }
137
        else{
138
            if (this->m_h == c.m_h && this->m_min < c.m_min){
139
                return true;
140
            }
141
        }
142
        return false;
143
    }
144
    /////////////////////////////////////////////////////////////////////////////////////
145
    bool operator > (const Clock& c){
146
        if (this->m_h > c.m_h){
147
            return true;
148
        }
149
        else{
150
            if (this->m_h == c.m_h && this->m_min > c.m_min){
151
                return true;
152
            }
153
        }
154
        return false;
155
    }
156
    /////////////////////////////////////////////////////////////////////////////////////
157
    bool operator >= (const Clock& c){
158
        if (this->m_h > c.m_h){
159
            return true;
160
        }
161
        else if (this->m_h == c.m_h){
162
163
            if (this->m_min >= c.m_min){
164
                return true;
165
            }
166
        }
167
        return false;
168
    }
169
    /////////////////////////////////////////////////////////////////////////////////////
170
    bool operator <= (const Clock& c){
171
        if (this->m_h < c.m_h){
172
            return true;
173
        }
174
        else if (this->m_h == c.m_h){
175
176
            if (this->m_min <= c.m_min){
177
                return true;
178
            }
179
        }
180
        return false;
181
    }
182
    /////////////////////////////////////////////////////////////////////////////////////
183
    Clock  operator + (const Clock& c){
184
        unsigned int minutes, hours;
185
        minutes = m_min+ c.m_min;
186
        hours = m_h + c.m_h;
187
        if (minutes >59){
188
            minutes =  minutes % 60;
189
            hours+=1;
190
        }
191
        if (hours >= 24){
192
            hours-=24;
193
        }
194
        return  Clock(hours, minutes);
195
196
    }
197
    /////////////////////////////////////////////////////////////////////////////////////
198
    Clock&  operator += (const Clock& c){
199
        unsigned int minutes, hours;
200
        minutes = m_min+ c.m_min;
201
        hours = m_h + c.m_h;
202
        if (minutes >59){
203
            minutes =  minutes % 60;
204
            hours+=1;
205
        }
206
        if (hours >= 24){
207
            hours-=24;
208
        }
209
        this->m_h = hours;
210
        this->m_min = minutes;
211
        return *this;
212
213
    }
214
    /////////////////////////////////////////////////////////////////////////////////////
215
216
    unsigned int toSeconds(){
217
        return toSeconds(Clock(this->m_h, this->m_min) );
218
    }
219
    /////////////////////////////////////////////////////////////////////////////////////
220
221
    static unsigned int toSeconds(Clock t){
222
        return ((t.m_h*60) + t.m_min)*60;
223
    }
224
    /////////////////////////////////////////////////////////////////////////////////////
225
226
    static Clock fromSeconds(unsigned int sec){
227
        unsigned int h = sec/3600;
228
        unsigned int min = sec%3600;
229
        min = min/60;
230
        return Clock(h,min);
231
    }
232
    /////////////////////////////////////////////////////////////////////////////////////
233
234
    static Clock periodOfTime(Clock start, Clock end)
235
    {
236
        if (end >= start){
237
            return Clock::fromSeconds(end.toSeconds() - start.toSeconds()  );
238
        }
239
        else{
240
            return Clock::fromSeconds(end.toSeconds() + ( Clock::toSeconds(Clock(23,59))+ 60 - start.toSeconds() ) );
241
        }
242
        //return diff;
243
    }
244
    ////////////////////////////////////////////////////////////////////////////////////
245
    static unsigned int getUnixTime()
246
    {
247
        return static_cast<unsigned int> (std::time(nullptr));
248
    }
249
    /////////////////////////////////////////////////////////////////////////////////////
250
#ifdef BT_TEST
251
    static void setTime_forBT_usage(int h, int m)
252
6
    {
253
6
        m_BT_H = h;
254
6
        m_BT_M = m;
255
6
    }
256
#endif
257
    /////////////////////////////////////////////////////////////////////////////////////
258
    static Clock getTime()
259
    {
260
#ifdef BT_TEST
261
        return Clock(m_BT_H,m_BT_M);
262
#else
263
        time_t now = time(0);
264
        tm *ltm = localtime(&now);
265
        return Clock( static_cast <unsigned int>(ltm->tm_hour),static_cast <unsigned int>(ltm->tm_min) );
266
#endif
267
    }
268
    /////////////////////////////////////////////////////////////////////////////////////
269
    void stopwatchStart()
270
    {
271
        m_time = std::time(nullptr);
272
    }
273
    /////////////////////////////////////////////////////////////////////////////////////
274
    unsigned int  stopwatchStopAndGetResult()
275
    {
276
        return static_cast<unsigned int>(std::time(nullptr) - m_time);
277
    }
278
};
279
280
enum class STATE {
281
    OFF,
282
    ON,
283
    UNKNOWN,
284
    PLAY,
285
    PAUSE,
286
    STOP,
287
    ACTIVE,
288
    DEACTIVE,
289
    WORKING,
290
    DEFINE,
291
    UNDEFINE,
292
    LOCK,
293
    UNLOCK,
294
    EMPTY,
295
    FULL,
296
    SEND_OK,
297
    SEND_NOK
298
    //WARNING remember add new state to stateToString() usefull.cpp
299
};
300
301
302
std::string stateToString(STATE s);
303
STATE stringToState(const std::string& s);
304
305
#endif
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/functions/tests/functions_stub.cpp
Line
Count
Source (jump to first uncovered line)
1
#include "../functions.h"
2
#include "test_data.h"
3
4
void useful_F::clearThreadArray(thread_data *my_data)
5
8
{
6
8
    std::cout << "useful_F::clearThreadArray(thread_data *my_data)" << std::endl;
7
8
}
8
9
10
11
int useful_F::runLinuxCommand(const std::string& cmd){
11
11
    std::cout << "runLinuxCommand(): " << cmd << std::endl;
12
11
    return TEST_DATA::runLinuxCommandReturn;
13
11
}
14
15
bool useful_F::go_while = true;
16
bool useful_F::workServer = true;
17
18
0
void useful_F::button_interrupt(){}
19
20
51
std::string useful_F::send_to_arduino(thread_data *my_data, const std::string& d){
21
51
    puts("useful_F::send_to_arduino()");
22
51
    return TEST_DATA::return_send_to_arduino;
23
51
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDom_server_OOP.h
Line
Count
Source
1
#ifndef GLOBAL_H
2
#define GLOBAL_H
3
4
#include <iostream>
5
#include <fstream>
6
#include <string>
7
#include <cstdlib>
8
#include <pthread.h>
9
#include <stdio.h>
10
#include <stdlib.h>
11
#include <sys/socket.h>
12
#include <sys/types.h>
13
#include <netinet/in.h>
14
#include <vector>
15
#include <thread>
16
#include <arpa/inet.h>
17
#include <netinet/in.h>
18
#include <unistd.h>
19
#include <sys/fcntl.h>
20
#include <unistd.h>
21
#include <errno.h>
22
#include <signal.h>
23
#include <time.h>
24
#include <wiringPi.h>
25
#include <chrono>
26
#include <array>
27
28
// MOJE BIBLIOTEKI
29
#include "KEY/key.h"
30
#include "logger/logger.hpp"
31
#include "files_tree/files_tree.h"
32
#include "menu_tree/menu_tree.h"
33
#include "LCD_c/lcd_c.h"
34
#include "command/command.h"
35
#include "../libs/event_counters/event_counters_handler.h"
36
#include "iDomTools/idomtools.h"
37
#include "iDomStatus/idomstatus.h"
38
#include "iDomSaveState/idom_save_state.h"
39
40
#define log_file_cout  f_log //std::cout zmien f_log na std::cout i bedzie wypisywac na ekran
41
#define log_file_mutex f_log
42
43
enum class iDomStateEnum{
44
    CLOSE = 0,
45
    RELOAD,
46
    ERROR,
47
    WORKING,
48
    HARD_RELOAD
49
};
50
51
namespace iDomConst
52
{
53
constexpr int MAX_CONNECTION = 10;
54
constexpr int FREE  = 1;
55
constexpr int RS232 = 11;
56
constexpr int CLOCK = 12;
57
constexpr int ok    = 0;
58
constexpr int GPIO_SPIK = 21;
59
constexpr int GPIO_PRINTER = 22;
60
constexpr int BUTTON_PIN = 25;
61
}
62
struct ALERT
63
{
64
    Clock time;
65
    STATE state = STATE::DEACTIVE;
66
    unsigned int fromVolume = 48;
67
    unsigned int toVolume = 58;
68
    unsigned int radioID = 8;
69
};
70
71
extern std::string _logfile;
72
extern Logger log_file_mutex;
73
extern std::string buffer;
74
75
enum class TEMPERATURE_STATE;
76
enum class PILOT_KEY;
77
78
struct MPD_info{
79
    std::string title   = "NULL";
80
    std::string radio   = "NULL";
81
    std::string artist  = "NULL";
82
    int volume = 0;
83
    bool isPlay = false;
84
    int currentSongID = 0;
85
    std::vector <std::string> songList = {"NULL"};
86
};
87
struct s_pointer{
88
    unsigned int *ptr_who;
89
    int32_t *ptr_buf;
90
};
91
92
struct Thread_array_struc {
93
    std::thread thread;
94
    std::thread::id thread_ID = std::thread::id(0);
95
    std::string thread_name;
96
    int thread_socket = 0;
97
};
98
99
struct address_another_servers {
100
    int id;
101
    std::string SERVER_IP;
102
};
103
104
struct FTP_SERVER{
105
    std::string URL;
106
    std::string user;
107
    std::string pass;
108
};
109
struct iDOM_STATE{
110
    STATE houseState = STATE::UNDEFINE;
111
112
};
113
114
struct config{
115
    std::string portRS232;
116
    std::string portRS232_clock;
117
    std::string BaudRate;
118
    std::string RFLinkPort;
119
    std::string RFLinkBaudRate;
120
    int PORT;
121
    std::string SERVER_IP;
122
    std::string MPD_IP;
123
    std::string MOVIES_DB_PATH;
124
    std::string MENU_PATH;
125
    std::string THREAD_MPD   = "NULL";
126
    std::string THREAD_IRDA  = "NULL";
127
    std::string THREAD_CRON  = "NULL";
128
    std::string THREAD_RS232 = "NULL";
129
    std::string THREAD_DUMMY = "NULL";
130
    std::string TS_KEY= " gg ";
131
    std::string cameraLedON = "";
132
    std::string cameraLedOFF ="";
133
    std::string cameraURL="";
134
    std::string facebookAccessToken = "";
135
    std::string viberToken = "NULL";
136
    std::string viberAvatar;
137
    std::vector <std::string> viberReceiver;
138
    std::string viberSender;
139
    std::string radio433MHzConfigFile;
140
    std::string omxplayerFile = "NULL";
141
    int ID_server = 0;
142
    int v_delay;
143
    bool encrypted = true;
144
145
    FTP_SERVER ftpServer;
146
    std::string lightningApiURL = "NULL";
147
    std::string saveFilePath = "NULL";
148
};
149
150
struct LED_Strip{
151
    std::string from;
152
    std::string to;
153
    std::string R;
154
    std::string G;
155
    std::string B;
156
    std::string colorName;
157
158
    LED_Strip (int from, int to, int r, int g, int b, std::string colorName = "NULL"):from(std::to_string(from)),
159
        to(std::to_string(to)),
160
        R(std::to_string(r)),
161
        G(std::to_string(g)),
162
        B(std::to_string(b)),
163
        colorName(colorName)
164
    {
165
166
    }
167
    LED_Strip (const std::string& from,
168
               const std::string& to,
169
               const std::string& r,
170
               const std::string& g,
171
               const std::string& b,
172
               const std::string& colorName = "NULL"):
173
        from(from),
174
        to(to),
175
        R(r),
176
        G(g),
177
        B(b),
178
        colorName(colorName)
179
1
    {
180
1
181
1
    }
182
183
    void set (const std::string& from,
184
              const std::string& to,
185
              const std::string& r,
186
              const std::string& g,
187
              const std::string& b,
188
              const std::string& colorName = "NULL")
189
1
    {
190
1
        this->from =from;
191
1
        this->to = to;
192
1
        R = r;
193
1
        G = g;
194
1
        B = b;
195
1
        this->colorName =colorName;
196
1
    }
197
198
1
    void set (int from, int to, int r, int g, int b, std::string colorName = "NULL"){
199
1
        this->from = std::to_string(from);
200
1
        this->to = std::to_string(to);
201
1
        R = std::to_string(r);
202
1
        G = std::to_string(g);
203
1
        B = std::to_string(b);
204
1
        this->colorName =colorName;
205
1
    }
206
207
12
    std::string getColorName() const{
208
12
        return colorName;
209
12
    }
210
211
19
    std::string get(unsigned int _from, unsigned int _to) const{
212
19
        if (_from != 0 || _to != 60){
213
10
            return "LED:["+std::to_string(_from)+"-"+std::to_string(_to)+"-"+R+"-"+G+"-"+B+"];";
214
10
        }
215
19
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
216
19
    }
217
218
    std::string makeCommand(const std::string& from,
219
                            const std::string& to,
220
                            const std::string& R,
221
                            const std::string& G,
222
1
                            const std::string& B){
223
1
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
224
1
    }
225
};
226
227
struct pilot_led{
228
    unsigned int counter=0;
229
    std::vector<LED_Strip> colorLED   = { LED_Strip(1,60,237,145,33 ,"carrot orange"),
230
                                          LED_Strip(1,60,255,0,0    ,"red"),
231
                                          LED_Strip(1,60,0,255,0    ,"green"),
232
                                          LED_Strip(1,60,0,0,255    ,"blue"),
233
                                          LED_Strip(1,60,255,255,255,"white"),
234
                                          LED_Strip(1,60,255,255,0  ,"yellow"),
235
                                          LED_Strip(1,60,0,255,255  ,"cyan"),
236
                                          LED_Strip(1,60,255,0,255  ,"magenta")
237
                                        };
238
};
239
240
class command; // for struc thread_data req
241
class iDomTOOLS;
242
class RADIO_EQ_CONTAINER;
243
class RFLinkHandler;
244
245
struct thread_data{
246
    int s_client_sock;
247
    struct sockaddr_in from;
248
    struct config *server_settings = NULL;
249
    struct s_pointer pointer;
250
    LCD_c *mainLCD = NULL;
251
    files_tree *main_tree = NULL;
252
    menu_tree *main_MENU = NULL;
253
    iDomTOOLS *main_iDomTools = NULL;
254
    RFLinkHandler *main_RFLink = NULL;
255
    std::array<Thread_array_struc, iDomConst::MAX_CONNECTION> *main_THREAD_arr = NULL;
256
    time_t start;
257
    time_t now_time;
258
    int sleeper;
259
    std::map <std::string, std::unique_ptr <KEY> > key_map;
260
    MPD_info *ptr_MPD_info = NULL;
261
    pilot_led * ptr_pilot_led = NULL;
262
    std::map <std::string, std::unique_ptr<command> >* commandMapPtr = NULL;
263
    event_counters_handler myEventHandler;
264
    std::string encriptionKey = "40%";
265
    iDomSTATUS *main_iDomStatus;
266
    iDOM_STATE idom_all_state;
267
    ALERT alarmTime;
268
    std::shared_ptr<RADIO_EQ_CONTAINER> main_REC;
269
    iDomStateEnum iDomProgramState = iDomStateEnum::WORKING;
270
};
271
272
struct thread_data_rs232{
273
    std::string portRS232;
274
    std::string portRS232_clock;
275
    std::string BaudRate;
276
    struct s_pointer pointer;
277
};
278
279
#endif // GLOBAL_H
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDomSaveState/idom_save_state.cpp
Line
Count
Source
1
#include <iostream>     // std::cout
2
#include <fstream>
3
#include "idom_save_state.h"
4
#include "../iDom_server_OOP.h"
5
6
iDom_SAVE_STATE::iDom_SAVE_STATE(const std::string &path): m_path(path)
7
50
{
8
50
#ifdef BT_TEST
9
50
    puts("iDom_SAVE_STATE::iDom_SAVE_STATE()");
10
50
#endif
11
50
}
12
13
iDom_SAVE_STATE::~iDom_SAVE_STATE()
14
50
{
15
50
#ifdef BT_TEST
16
50
    puts("iDom_SAVE_STATE::~iDom_SAVE_STATE()");
17
50
#endif
18
50
}
19
20
nlohmann::json iDom_SAVE_STATE::read()
21
3
{
22
3
    std::lock_guard<std::mutex> lGuard(m_mutex);
23
3
    // read a JSON file
24
3
    std::ifstream i(m_path);
25
3
    nlohmann::json j;
26
3
    i >> j;
27
3
28
3
    log_file_mutex.mutex_lock();
29
3
    log_file_cout << INFO << "czytam zapisany stan parametrow iDom" << std::endl;
30
3
    log_file_mutex.mutex_unlock();
31
3
32
3
    return j;
33
3
}
34
35
void iDom_SAVE_STATE::write(const nlohmann::json &jj)
36
48
{
37
48
    std::lock_guard<std::mutex> lGuard(m_mutex);
38
48
    // write prettified JSON to another file
39
48
    std::ofstream o(m_path);
40
48
    o << std::setw(4) << jj << std::endl;
41
48
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDomTools/lightning.h
Line
Count
Source (jump to first uncovered line)
1
#ifndef LIGHTNING_H
2
#define LIGHTNING_H
3
#include <iostream>
4
5
#include "../../libs/Statistic/statistic.h"
6
#include "../../libs/useful/useful.h"
7
8
#include "idomtools_useful.h"
9
#include "json.hpp"
10
11
class CARDINAL_DIRECTIONS{
12
public:
13
    enum class CARDINAL_DIRECTIONS_ENUM{
14
        /*
15
           N
16
        NNW NNE
17
      NW       NE
18
   WNW         ENE
19
 W            E
20
   WSW       ESE
21
      SW     SE
22
        SSW  SSE
23
           S
24
    */
25
26
        N = 1,NNE,NE,ENE,E,ESE,SE,SSE,S,SSW,SW,WSW,W,WNW,NW,NNW,ERROR
27
    };
28
148
    static CARDINAL_DIRECTIONS_ENUM stringToCardinalDirectionsEnum(std::string s){
29
148
        if (s == "N")      return CARDINAL_DIRECTIONS_ENUM::N;
30
148
        else if (s == "NNE")    return CARDINAL_DIRECTIONS_ENUM::NNE;
31
147
        else if (s == "NE")     return CARDINAL_DIRECTIONS_ENUM::NE;
32
135
        else if (s == "ENE")    return CARDINAL_DIRECTIONS_ENUM::ENE;
33
129
        else if (s == "E")      return CARDINAL_DIRECTIONS_ENUM::E;
34
51
        else if (s == "ESE")    return CARDINAL_DIRECTIONS_ENUM::ESE;
35
3
        else if (s == "SE")     return CARDINAL_DIRECTIONS_ENUM::SE;
36
3
        else if (s == "SSE")    return CARDINAL_DIRECTIONS_ENUM::SSE;
37
3
        else if (s == "S")      return CARDINAL_DIRECTIONS_ENUM::S;
38
3
        else if (s == "SSW")    return CARDINAL_DIRECTIONS_ENUM::SSW;
39
3
        else if (s == "SW")     return CARDINAL_DIRECTIONS_ENUM::SW;
40
3
        else if (s == "WSW")    return CARDINAL_DIRECTIONS_ENUM::WSW;
41
3
        else if (s == "W")      return CARDINAL_DIRECTIONS_ENUM::W;
42
1
        else if (s == "WNW")    return CARDINAL_DIRECTIONS_ENUM::WNW;
43
1
        else if (s == "NW")     return CARDINAL_DIRECTIONS_ENUM::NW;
44
1
        else if (s == "NNW")    return CARDINAL_DIRECTIONS_ENUM::NNW;
45
1
        else                    return CARDINAL_DIRECTIONS_ENUM::ERROR;
46
148
    }
47
48
2
    static std::string cardinalDirectionsEnumToString(CARDINAL_DIRECTIONS_ENUM e){
49
2
        switch (e){
50
0
        case CARDINAL_DIRECTIONS_ENUM::N:
51
0
            return "N";
52
0
        case CARDINAL_DIRECTIONS_ENUM::NNE:
53
0
            return "NNE";
54
0
        case CARDINAL_DIRECTIONS_ENUM:: NE:
55
0
            return "NE";
56
0
        case CARDINAL_DIRECTIONS_ENUM::ENE:
57
0
            return "ENE";
58
0
        case CARDINAL_DIRECTIONS_ENUM::E:
59
0
            return "E";
60
1
        case CARDINAL_DIRECTIONS_ENUM::ESE:
61
1
            return "ESE";
62
0
        case CARDINAL_DIRECTIONS_ENUM::SE:
63
0
            return "SE";
64
0
        case CARDINAL_DIRECTIONS_ENUM::SSE:
65
0
            return "SSE";
66
0
        case CARDINAL_DIRECTIONS_ENUM::S:
67
0
            return "S";
68
0
        case CARDINAL_DIRECTIONS_ENUM::SSW:
69
0
            return "SSW";
70
0
        case CARDINAL_DIRECTIONS_ENUM::SW:
71
0
            return "SW";
72
0
        case CARDINAL_DIRECTIONS_ENUM::WSW:
73
0
            return "WSW";
74
0
        case CARDINAL_DIRECTIONS_ENUM::W:
75
0
            return "W";
76
0
        case CARDINAL_DIRECTIONS_ENUM::WNW:
77
0
            return "WNW";
78
0
        case CARDINAL_DIRECTIONS_ENUM::NW:
79
0
            return "NW";
80
0
        case CARDINAL_DIRECTIONS_ENUM::NNW:
81
0
            return "NNW";
82
1
        default:
83
1
            return "UNKNOWN DIRECTION";
84
0
        }
85
2
    }
86
    static std::string cardinalDirectionsEnumToHuman(CARDINAL_DIRECTIONS_ENUM e){
87
        switch (e){
88
        case CARDINAL_DIRECTIONS_ENUM::N:
89
            return "północ";
90
        case CARDINAL_DIRECTIONS_ENUM::NNE:
91
            return "północ - północny wschód";
92
        case CARDINAL_DIRECTIONS_ENUM:: NE:
93
            return "północny wschód";
94
        case CARDINAL_DIRECTIONS_ENUM::ENE:
95
            return "wschód - północny wschód";
96
        case CARDINAL_DIRECTIONS_ENUM::E:
97
            return "wschód";
98
        case CARDINAL_DIRECTIONS_ENUM::ESE:
99
            return "wschód - południowy wschód";
100
        case CARDINAL_DIRECTIONS_ENUM::SE:
101
            return "południowy wschód";
102
        case CARDINAL_DIRECTIONS_ENUM::SSE:
103
            return "południe - południowy wschód";
104
        case CARDINAL_DIRECTIONS_ENUM::S:
105
            return "południe";
106
        case CARDINAL_DIRECTIONS_ENUM::SSW:
107
            return "południe - południowy zachów";
108
        case CARDINAL_DIRECTIONS_ENUM::SW:
109
            return "południowy zachów";
110
        case CARDINAL_DIRECTIONS_ENUM::WSW:
111
            return "zachód - południowy zachów";
112
        case CARDINAL_DIRECTIONS_ENUM::W:
113
            return "zachód";
114
        case CARDINAL_DIRECTIONS_ENUM::WNW:
115
            return "zachód - północny zachód";
116
        case CARDINAL_DIRECTIONS_ENUM::NW:
117
            return "północny zachód";
118
        case CARDINAL_DIRECTIONS_ENUM::NNW:
119
            return "północ - północny zachód";
120
        default:
121
            return "UNKNOWN DIRECTION";
122
        }
123
    }
124
    struct ALARM_INFO{
125
        ALARM_INFO():
126
            riseAlarm(false),
127
            timestamp(0),
128
            distance(0.0),
129
            bearingENG(CARDINAL_DIRECTIONS::CARDINAL_DIRECTIONS_ENUM::ERROR)
130
        {
131
            data << "NULL";
132
        }
133
        ALARM_INFO(const ALARM_INFO &s):
134
            riseAlarm(s.riseAlarm),
135
            data(s.data.str()),
136
            timestamp(s.timestamp),
137
            distance(s.distance),
138
            bearingENG(s.bearingENG)
139
        {
140
        }
141
        ALARM_INFO& operator = (const ALARM_INFO& s)
142
14
        {
143
14
            this->data.str(std::string());
144
14
            this->riseAlarm = s.riseAlarm;
145
14
            this->data << s.data.str();
146
14
            this->timestamp = s.timestamp;
147
14
            this->distance = s.distance;
148
14
            this->bearingENG = s.bearingENG;
149
14
            return *this;
150
14
        }
151
152
        bool riseAlarm;
153
        std::stringstream data;
154
        unsigned int timestamp; //second
155
        double distance; //km
156
        CARDINAL_DIRECTIONS::CARDINAL_DIRECTIONS_ENUM bearingENG;
157
    };
158
};
159
160
class LIGHTNING
161
{
162
public:
163
    LIGHTNING();
164
    ~LIGHTNING();
165
    CARDINAL_DIRECTIONS::ALARM_INFO lightningAlert(nlohmann::json jj);
166
    bool checkLightningAlert(CARDINAL_DIRECTIONS::ALARM_INFO* info);
167
private:
168
    bool alarmState = false;
169
    Clock lightningTime;
170
    double oldDistance = 0.0;
171
};
172
173
#endif // LIGHTNING_H
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDomSaveState/test/iDomSaveState_BT.cpp
Line
Count
Source
1
#include <gtest/gtest.h>
2
3
#include "test_data.h"
4
#include "../idom_save_state.h"
5
#include "json.hpp"
6
7
TEST(iDomSaveState, write_and_read)
8
1
{
9
1
    iDom_SAVE_STATE test_saveState("/mnt/ramdisk/iDomStateTest.save");
10
1
    nlohmann::json test_json ;
11
1
12
1
    test_json["happy"] = true;
13
1
    test_json["pi"] = 3.14;
14
1
15
1
    nlohmann::json test_json_in_json;
16
1
    test_json_in_json["name"] = "cyniu";
17
1
    test_json_in_json["age"] = 30;
18
1
19
1
    test_json["person"] = test_json_in_json;
20
1
21
1
    test_saveState.write(test_json);
22
1
    nlohmann::json test_json2 = test_saveState.read();
23
2
    EXPECT_DOUBLE_EQ(test_json.at("pi").get<double>(),
24
2
                     test_json2.at("pi").get<double>()) << "wartosci pi nie sa rowne";
25
1
26
2
    EXPECT_TRUE(test_json2.at("happy").get<bool>()) << " nie jest happy";
27
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDomTools/test/iDom_server_BT.cpp
Line
Count
Source
1
#include <gtest/gtest.h>
2
#include <curl/curl.h>
3
#include "iDomTools_fixture.h"
4
5
class iDom_server_Class : public iDomTOOLS_ClassTest
6
{
7
protected:
8
    TEST_JSON test_Json;
9
    LIGHTNING test_lightning;
10
    CARDINAL_DIRECTIONS::ALARM_INFO test_struct;
11
    virtual void SetUp() final
12
1
    {
13
1
        std::cout << "konfiguracja przed testem iDom_server_Class " <<std::endl;
14
1
    }
15
16
    virtual void TearDown() final
17
1
    {
18
1
        std::cout << "czyszczenie po tescie iDom_server_Class " <<std::endl;
19
1
    }
20
};
21
22
TEST_F(iDom_server_Class, LED_Strip )
23
1
{
24
1
    LED_Strip test_LED("1","60","255","255","255", "WHITE");
25
1
    EXPECT_STREQ(test_LED.getColorName().c_str(), "WHITE");
26
1
    EXPECT_STREQ(test_LED.get(0,60).c_str(),"LED:[1-60-255-255-255];");
27
1
    EXPECT_STREQ(test_LED.makeCommand("1","60","128","128","128").c_str(),"LED:[1-60-128-128-128];");
28
1
29
1
    test_LED.set("1","60","0","255","0","UNKNOWN");
30
1
31
1
    EXPECT_STREQ(test_LED.getColorName().c_str(), "UNKNOWN");
32
1
    EXPECT_STREQ(test_LED.get(0,60).c_str(),"LED:[1-60-0-255-0];");
33
1
34
1
    test_LED.set(50,51,1,2,3,"BLACK");
35
1
36
1
    EXPECT_STREQ(test_LED.getColorName().c_str(), "BLACK");
37
    EXPECT_STREQ(test_LED.get(0,60).c_str(),"LED:[50-51-1-2-3];");
38
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDomStatus/idomstatus.cpp
Line
Count
Source
1
#include "idomstatus.h"
2
3
iDomSTATUS::iDomSTATUS()
4
198
{
5
198
}
6
7
void iDomSTATUS::addObject(std::string name, STATE st)
8
1.17k
{
9
1.17k
    std::lock_guard < std::mutex > lock ( m_lockGuard);
10
1.17k
    m_stateMAP.insert(std::make_pair(name,st));
11
1.17k
}
12
13
void iDomSTATUS::setObjectState(const std::string& name, STATE st)
14
107
{
15
107
    std::lock_guard < std::mutex > lock ( m_lockGuard);
16
107
    auto i = m_stateMAP.find(name);
17
107
    if (i != m_stateMAP.end()){
18
82
        i->second = st;
19
82
    }
20
25
    else
21
25
    {
22
25
        lock.~lock_guard();
23
25
        addObject(name,st);
24
25
    }
25
107
}
26
27
STATE iDomSTATUS::getObjectState(const std::string& name)
28
77
{
29
77
    std::lock_guard < std::mutex > lock ( m_lockGuard);
30
77
    auto i = m_stateMAP.find(name);
31
77
    if (i != m_stateMAP.end())
32
69
    {
33
69
        return i->second;
34
69
    }
35
8
    return STATE::UNKNOWN;
36
8
}
37
38
std::string iDomSTATUS::getObjectStateString(const std::string& name)
39
144
{
40
144
    std::lock_guard < std::mutex > lock ( m_lockGuard);
41
144
    auto i = m_stateMAP.find(name);
42
144
    if (i != m_stateMAP.end())
43
105
    {
44
105
        return stateToString( i->second);
45
105
    }
46
39
    return stateToString(STATE::UNKNOWN) + " "+name;
47
39
}
48
49
std::string iDomSTATUS::getAllObjectsStateString()
50
3
{
51
3
    std::stringstream st;
52
3
    st << "state: ";
53
3
    std::lock_guard < std::mutex > lock( m_lockGuard);
54
3
    for (auto elm : m_stateMAP)
55
20
    {
56
20
        st << elm.first << "=";
57
20
        st << stateToString(elm.second) << " ";
58
20
    }
59
3
    return st.str();
60
3
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDomTools/test/idomTools_BT.cpp
Line
Count
Source
1
#include <gtest/gtest.h>
2
#include <curl/curl.h>
3
4
#include "iDomTools_fixture.h"
5
6
TEST_F(iDomTOOLS_ClassTest, smog)
7
1
{
8
1
    std::string smog = test_idomTOOLS->getSmog();
9
1
    puts(smog.c_str());
10
1
    puts(" smog");
11
1
    ASSERT_GE(smog.size(),1);
12
1
13
1
    unsigned int smog_int = std::stoi(smog);
14
1
    ASSERT_GT(smog_int,1);
15
1
    ASSERT_LT(smog_int,1000);
16
1
}
17
18
TEST_F(iDomTOOLS_ClassTest, hasTemperatureChange)
19
1
{
20
1
    std::cout << "##################################### 0" <<std::endl;
21
1
22
1
    TEST_DATA::return_send_to_arduino = "20.0:-1.0;";
23
1
    test_idomTOOLS->send_temperature_thingSpeak();
24
1
    EXPECT_EQ(test_idomTOOLS->allThermometer.getLastState("outside"),TEMPERATURE_STATE::Under);
25
1
    EXPECT_EQ(test_idomTOOLS->allThermometer.getLastState("inside"),TEMPERATURE_STATE::NoChanges);
26
1
    std::cout << "##################################### 1" <<std::endl;
27
1
28
1
    TEST_DATA::return_send_to_arduino = "25.4:0.0;";
29
1
    test_idomTOOLS->send_temperature_thingSpeak();
30
1
31
1
    EXPECT_EQ(test_idomTOOLS->allThermometer.getLastState("outside"),TEMPERATURE_STATE::NoChanges);
32
1
    EXPECT_EQ(test_idomTOOLS->allThermometer.getLastState("inside"),TEMPERATURE_STATE::Over);
33
1
34
1
    std::cout << "##################################### 2" <<std::endl;
35
1
36
1
    TEST_DATA::return_send_to_arduino = "21.0:1.0;";
37
1
    test_idomTOOLS->send_temperature_thingSpeak();
38
1
    EXPECT_EQ(test_idomTOOLS->allThermometer.getLastState("outside"),TEMPERATURE_STATE::Over);
39
1
    EXPECT_EQ(test_idomTOOLS->allThermometer.getLastState("inside"),TEMPERATURE_STATE::Under);
40
1
41
1
    std::cout << "##################################### 3" <<std::endl;
42
1
    TEST_DATA::return_send_to_arduino = "21.0:5.0;";
43
1
    test_idomTOOLS->send_temperature_thingSpeak();
44
1
    EXPECT_EQ(test_idomTOOLS->allThermometer.getLastState("outside"),TEMPERATURE_STATE::NoChanges);
45
1
    EXPECT_EQ(test_idomTOOLS->allThermometer.getLastState("inside"),TEMPERATURE_STATE::NoChanges);
46
1
47
1
    std::cout << "##################################### 4" <<std::endl;
48
1
    TEST_DATA::return_send_to_arduino = "21.0:4.0;";
49
1
    test_idomTOOLS->send_temperature_thingSpeak();
50
1
    EXPECT_EQ(test_idomTOOLS->allThermometer.getLastState("outside"),TEMPERATURE_STATE::NoChanges);
51
1
    EXPECT_EQ(test_idomTOOLS->allThermometer.getLastState("inside"),TEMPERATURE_STATE::NoChanges);
52
1
    std::cout << "##################################### 5" <<std::endl;
53
1
54
1
    TEST_DATA::return_send_to_arduino = "31.9:11.11;";
55
1
    test_idomTOOLS->send_temperature_thingSpeak();
56
1
    EXPECT_EQ(test_idomTOOLS->allThermometer.getLastState("outside"),TEMPERATURE_STATE::NoChanges);
57
1
    EXPECT_EQ(test_idomTOOLS->allThermometer.getLastState("inside"),TEMPERATURE_STATE::Over);
58
1
    std::cout << "##################################### 6" <<std::endl;
59
1
60
1
    ////// getThermoStats
61
1
62
1
    std::cout <<"WYNIK: " << test_idomTOOLS->getThermoStats("inside") <<std::endl;
63
1
}
64
65
TEST_F(iDomTOOLS_ClassTest, weatherAlert)
66
1
{
67
1
    std::string test_data_from_www = "    <div style=\"margin:0;padding:0;width:350px;font:0.8em Lucida,Arial,sans-seri                                                                  f;background:#FFC\">\
68
1
            <p style=\"margin:1px;padding:1px;text-align:center;background:#FF9;borde \                                                                 r:1px dotted\"><b><a href=\"http://burze.dzis.net?page=wyszukiwarka&amp;miejscowos\                                                                  c=krakow\" target=\"_blank\" style=\"color:#00E\">krakow</a></b>\
69
1
            <i>(50°03'N 19°57'E)</i>\
70
1
            </p>\
71
1
            <dl style=\"margin:1px 1px 0 1px;padding:0;cl                                                                  ear:both;background:#FFD;border:1px dotted;overflow:auto;color:green;text-align:\                                                                  center\">Zarejestrowano 54 wyładowania atmosferyczne w promieniu 300km . Najbliższe 79.76km na zachód.\
72
1
            </dl>\
73
1
            \
74
1
            <dl style=\"margin:1px 1px 0 1px;padding:0;cl                                                                  ear:both;background:#FFD;border:1px dotted;overflow:auto;color:green;text-align:  \                                                                center\">Mróz, brak ostrzeżeń</dl>\
75
1
            \
76
1
            <dl style=\"margin:1px 1px 0 1px;padding:0;clear:both                                                                  ;background:#FFD;border:1px dotted;overflow:auto;color:green;text-align:center\">  \                                                                Upał, brak ostrzeżeń</dl>\
77
1
            \
78
1
            <dl style=\"margin:1px 1px 0 1px;padding:0;clear:both                                                                  ;background:#FFD;border:1px dotted;overflow:auto;color:green;text-align:center\">  \                                                                Wiatr, brak ostrzeżeń</dl>\
79
1
            \
80
1
            <dl style=\"margin:1px 1px 0 1px;padding:0;clear:both                                                                  ;background:#FFD;border:1px dotted;overflow:auto;color:green;text-align:center\">  \                                                                Opady, brak ostrzeżeń</dl>\
81
1
            \
82
1
            <dl style=\"margin:1px 1px 0 1px;padding:0;clear:both                                                                  ;background:#FFD;border:1px dotted;overflow:auto;color:green;text-align:center\">  \                                                                Burze, brak ostrzeżeń</dl>\
83
1
            \
84
1
            <dl style=\"margin:1px 1px 0 1px;padding:0;clear:both                                                                  ;background:#FFD;border:1px dotted;overflow:auto;color:green;text-align:center\">  \                                                                Trąby powietrzne, brak ostrzeżeń</dl>\
85
1
            </div>";
86
1
87
1
88
1
            std::vector<WEATHER_ALER> test_WA;
89
1
    test_WA =  test_idomTOOLS->getAlert(test_data_from_www);
90
3
    EXPECT_EQ(1,test_WA.size()) << "ZŁY ROZMIAR VEKTORA WA";
91
1
}
92
93
1
TEST_F(iDomTOOLS_ClassTest, send_temperature_thingSpeak){
94
1
95
1
    TEST_DATA::return_send_to_arduino = "-2.3:-2";
96
1
    TEST_DATA::return_httpPost_expect = "NULL";
97
1
    EXPECT_STREQ(TEST_DATA::return_httpPost_expect.c_str(),"NULL");
98
1
    test_idomTOOLS->send_temperature_thingSpeak();
99
1
    std::cout << "DATA: "<< TEST_DATA::return_httpPost_expect <<std::endl;
100
1
    EXPECT_STREQ(TEST_DATA::return_httpPost_expect.c_str(),"httpPost");
101
1
}
102
103
TEST_F(iDomTOOLS_ClassTest, checkAlarm)
104
1
{
105
1
    blockQueue test_q;
106
1
    unsigned int fromVol = 48;
107
1
    unsigned int  toVol = 57;
108
1
109
1
    ///////////////////////////////////// to save
110
1
    test_status.setObjectState("house",STATE::UNLOCK);
111
1
    test_status.setObjectState("music", STATE::PLAY);
112
1
    test_status.setObjectState("speakers", STATE::ON);
113
1
    test_my_data.idom_all_state.houseState = STATE::LOCK;
114
1
115
1
    test_status.setObjectState("listwa",STATE::ON);
116
1
117
1
    test_alarmTime.time = Clock::getTime();
118
1
    test_alarmTime.state = STATE::ACTIVE;
119
1
    test_alarmTime.toVolume = 58;
120
1
    test_alarmTime.fromVolume = 48;
121
1
    test_status.setObjectState("alarm", test_alarmTime.state);
122
1
    test_my_data.alarmTime = test_alarmTime;
123
1
    useful_F::myStaticData = &test_my_data;
124
1
125
1
    //////////////////////////////////////////////////////////////
126
1
127
1
    test_my_data.alarmTime.time = Clock::getTime();
128
1
    test_my_data.alarmTime.state = STATE::ACTIVE;
129
1
130
1
    EXPECT_EQ(test_my_data.alarmTime.state, STATE::ACTIVE);
131
1
132
10
    for(unsigned int i = fromVol; i<toVol; ++i)
133
9
    {
134
9
        test_idomTOOLS->checkAlarm();
135
9
        test_q._get();
136
27
        EXPECT_EQ(test_my_data.alarmTime.state, STATE::WORKING)<< "zły stan w for " << i<< " "<< toVol;
137
27
        EXPECT_EQ(test_my_data.ptr_MPD_info->volume, i+1) << "zły poziom glosnosci w for";
138
9
    }
139
1
140
1
    test_idomTOOLS->checkAlarm();
141
1
142
3
    EXPECT_EQ(test_my_data.alarmTime.state, STATE::DEACTIVE) << "nie jest STATE::DEACTIVE";
143
3
    EXPECT_EQ(test_my_data.ptr_MPD_info->volume, toVol)<< "nie inkrementowane?";
144
1
145
1
}
146
147
TEST_F(iDomTOOLS_ClassTest, homeLockPlayStopMusic)
148
1
{
149
1
    ///////////////////////////////////// to save
150
1
    test_status.setObjectState("house",STATE::UNDEFINE);
151
1
    test_status.setObjectState("music", STATE::PLAY);
152
1
    test_status.setObjectState("speakers", STATE::ON);
153
1
    test_my_data.idom_all_state.houseState = STATE::LOCK;
154
1
155
1
    test_status.setObjectState("listwa",STATE::ON);
156
1
157
1
    test_alarmTime.time = Clock::getTime();
158
1
    test_alarmTime.state = STATE::ACTIVE;
159
1
    test_status.setObjectState("alarm", test_alarmTime.state);
160
1
161
1
    blockQueue test_q;
162
1
    test_q._clearAll();
163
1
    EXPECT_EQ(test_q._size(),0);
164
1
    EXPECT_EQ(test_status.getObjectState("house"),STATE::UNDEFINE);
165
1
    test_idomTOOLS->lockHome();
166
1
    EXPECT_EQ(test_status.getObjectState("house"),STATE::LOCK);
167
1
    test_idomTOOLS->MPD_play(&test_my_data);
168
1
    EXPECT_EQ(test_q._size(),0);
169
1
    test_idomTOOLS->unlockHome();
170
1
    EXPECT_EQ(test_status.getObjectState("house"),STATE::UNLOCK);
171
1
    test_idomTOOLS->MPD_play(&test_my_data);
172
1
    EXPECT_EQ(test_q._size(),1);
173
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::PLAY);
174
1
    EXPECT_EQ(test_q._size(),0);
175
1
    test_idomTOOLS->lockHome();
176
1
    EXPECT_EQ(test_status.getObjectState("house"),STATE::LOCK);
177
1
    test_idomTOOLS->MPD_stop();
178
1
    EXPECT_EQ(test_q._size(),1);
179
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::STOP);
180
1
    EXPECT_EQ(test_q._size(),0);
181
1
    EXPECT_EQ(test_status.getObjectState("house"),STATE::LOCK);
182
1
    std::string returnedString = test_status.getAllObjectsStateString();
183
1
    EXPECT_THAT(returnedString, testing::HasSubstr("LOCK"));
184
1
}
185
186
TEST_F(iDomTOOLS_ClassTest, buttonPressed)
187
1
{
188
1
    std::string button433MHz_id = "01e7be";
189
1
    std::string pressedButtonName = test_idomTOOLS->buttonPressed(button433MHz_id);
190
1
    EXPECT_EQ(1, test_my_data.main_REC->getButtonPointerVector().size());
191
1
    EXPECT_STREQ(std::to_string(button433MHz_id).c_str(),
192
1
                 test_my_data.main_REC->getButtonPointerVector().at(0)->getID().c_str());
193
1
    EXPECT_STREQ(pressedButtonName.c_str(), "locker");
194
1
195
1
    EXPECT_THROW(test_idomTOOLS->buttonPressed(button433MHz_id+"a"),
196
1
                 std::string);
197
1
}
198
199
TEST_F(iDomTOOLS_ClassTest, button433MHzPressedAction_lockerUnlock)
200
1
{
201
1
    blockQueue test_q;
202
1
    test_q._clearAll();
203
1
204
1
    test_idomTOOLS->unlockHome();
205
1
    EXPECT_EQ(test_status.getObjectState("house"),STATE::UNLOCK);
206
1
207
4
    for(auto i =0 ; i < 3; ++i){
208
3
        test_idomTOOLS->button433MHzPressedAction("locker");
209
3
    }
210
1
    EXPECT_EQ(test_status.getObjectState("house"),STATE::LOCK);
211
1
212
1
    EXPECT_EQ(test_q._size(),1);
213
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::STOP);
214
1
215
1
}
216
217
TEST_F(iDomTOOLS_ClassTest, button433MHzPressedAction_lockerLock)
218
1
{
219
1
    blockQueue test_q;
220
1
    test_q._clearAll();
221
1
222
3
    EXPECT_EQ(test_status.getObjectState("house"),STATE::UNDEFINE) << "nie jest UNDEFINED";
223
1
224
1
    test_idomTOOLS->button433MHzPressedAction("locker");
225
3
    EXPECT_EQ(test_status.getObjectState("house"),STATE::UNLOCK)<< "nie jest UNLOCK";
226
1
227
1
    EXPECT_EQ(test_q._size(),1);
228
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::PLAY);
229
1
    EXPECT_EQ(test_q._size(),0);
230
1
}
231
232
TEST_F(iDomTOOLS_ClassTest, testCPU_Load)
233
1
{
234
1
    std::cout <<"TEST LOAD" << std::endl;
235
1
    std::cout << test_idomTOOLS->getSystemInfo() << std::endl;
236
1
}
237
TEST_F(iDomTOOLS_ClassTest, stringToCardinalDirectionsEnum)
238
1
{
239
1
    EXPECT_EQ(CARDINAL_DIRECTIONS::stringToCardinalDirectionsEnum("NWWA"),
240
1
              CARDINAL_DIRECTIONS::CARDINAL_DIRECTIONS_ENUM::ERROR);
241
1
    EXPECT_EQ(CARDINAL_DIRECTIONS::stringToCardinalDirectionsEnum("N"),
242
1
              CARDINAL_DIRECTIONS::CARDINAL_DIRECTIONS_ENUM::N);
243
1
}
244
245
TEST_F(iDomTOOLS_ClassTest, cardinalDirectionsEnumToString)
246
1
{
247
1
    EXPECT_STREQ( CARDINAL_DIRECTIONS::cardinalDirectionsEnumToString(CARDINAL_DIRECTIONS::CARDINAL_DIRECTIONS_ENUM::ERROR).c_str(),
248
1
                  "UNKNOWN DIRECTION");
249
1
    EXPECT_STREQ( CARDINAL_DIRECTIONS::cardinalDirectionsEnumToString(CARDINAL_DIRECTIONS::CARDINAL_DIRECTIONS_ENUM::ESE).c_str(),
250
1
                  "ESE");
251
1
}
252
253
TEST_F(iDomTOOLS_ClassTest, saveState_readState)
254
1
{
255
1
    test_status.setObjectState("house",STATE::UNLOCK);
256
1
    //////////////////// mpd
257
1
    test_status.setObjectState("music", STATE::PLAY);
258
1
    test_status.setObjectState("speakers", STATE::ON);
259
1
    test_my_data.idom_all_state.houseState = STATE::LOCK;
260
1
261
1
    test_status.setObjectState("listwa",STATE::ON);
262
1
    test_alarmTime.time = Clock::getTime();
263
1
    test_alarmTime.state = STATE::ACTIVE;
264
1
    test_alarmTime.fromVolume = 0;
265
1
    test_alarmTime.toVolume = 100;
266
1
    test_alarmTime.radioID = 44;
267
1
    test_my_data.alarmTime = test_alarmTime;
268
1
    test_status.setObjectState("alarm", test_alarmTime.state);
269
1
270
1
    test_idomTOOLS->saveState_iDom();
271
1
272
1
    nlohmann::json testJson;
273
1
    std::ifstream i(test_server_set.saveFilePath);
274
1
    i >> testJson;
275
1
    EXPECT_STREQ(test_status.getObjectStateString("music").c_str(),
276
1
                 testJson.at("MPD").at("music").get<std::string>().c_str() );
277
1
    EXPECT_STREQ((test_status.getObjectStateString("alarm")).c_str(),
278
1
                 testJson.at("ALARM").at("alarm").get<std::string>().c_str() );
279
1
    EXPECT_EQ(test_alarmTime.radioID,
280
1
              testJson.at("ALARM").at("radioID").get<int>() );
281
1
    EXPECT_EQ(test_alarmTime.fromVolume,
282
1
              testJson.at("ALARM").at("fromVolume").get<int>() );
283
1
    EXPECT_EQ(test_alarmTime.toVolume,
284
1
              testJson.at("ALARM").at("toVolume").get<int>() );
285
1
    ////////////////////////////////// read
286
1
    test_idomTOOLS->readState_iDom();
287
1
    EXPECT_EQ(test_my_data.alarmTime.state,STATE::ACTIVE);
288
1
289
1
    test_my_data.server_settings->saveFilePath = "null";
290
1
    EXPECT_NO_THROW(test_idomTOOLS->readState_iDom());
291
1
}
292
293
TEST_F(iDomTOOLS_ClassTest, getLightningStruct)
294
1
{
295
1
    LIGHTNING test_lightning;
296
1
    test_struct = test_lightning.lightningAlert(test_Json.jj_lightning);
297
1
298
1
    test_idomTOOLS->setLightningStruct(test_struct);
299
1
300
1
    bool test_result = test_lightning.checkLightningAlert(&test_struct);
301
1
    EXPECT_TRUE(test_result);
302
1
303
1
    auto test_alert_info = test_idomTOOLS->getLightningStruct();
304
1
    EXPECT_EQ(test_alert_info.timestamp,210);
305
1
}
306
TEST_F(iDomTOOLS_ClassTest, checkLightning)
307
1
{
308
1
    test_my_data.server_settings->lightningApiURL = "http://cyniu88.no-ip.pl/test/json/lightning.json";
309
1
    test_idomTOOLS->checkLightning();
310
1
    auto test_alert_info = test_idomTOOLS->getLightningStruct();
311
1
    EXPECT_EQ(test_alert_info.timestamp,210);
312
1
}
313
314
TEST_F(iDomTOOLS_ClassTest, updateTemperatureStats)
315
1
{
316
1
    TEST_DATA::return_send_to_arduino = "12:12";
317
1
    test_idomTOOLS->updateTemperatureStats();
318
1
    TEST_DATA::return_send_to_arduino = "16:16";
319
1
    test_idomTOOLS->updateTemperatureStats();
320
1
321
1
    ////////////// maleje na mieskzaniu
322
1
    TEST_DATA::return_send_to_arduino = "12:16";
323
1
    test_idomTOOLS->updateTemperatureStats();
324
1
    EXPECT_THAT(TEST_DATA::return_viber_msg,testing::HasSubstr("temperatura maleje"));
325
1
    EXPECT_THAT(TEST_DATA::return_viber_msg,testing::HasSubstr("mieszkaniu"));
326
1
327
1
    ////////////// maleje na polu
328
1
    TEST_DATA::return_send_to_arduino = "12:12";
329
1
    test_idomTOOLS->updateTemperatureStats();
330
1
    EXPECT_THAT(TEST_DATA::return_viber_msg,testing::HasSubstr("temperatura maleje"));
331
1
    EXPECT_THAT(TEST_DATA::return_viber_msg,testing::HasSubstr("polu"));
332
1
333
1
    ////////////// rośnie na mieskzaniu
334
1
    TEST_DATA::return_send_to_arduino = "17:12";
335
1
    test_idomTOOLS->updateTemperatureStats();
336
1
    EXPECT_THAT(TEST_DATA::return_viber_msg,testing::HasSubstr("temperatura rośnie"));
337
1
    EXPECT_THAT(TEST_DATA::return_viber_msg,testing::HasSubstr("mieszkaniu"));
338
1
339
1
    ////////////// rośnie na polu
340
1
    TEST_DATA::return_send_to_arduino = "17:17";
341
1
    test_idomTOOLS->updateTemperatureStats();
342
1
    EXPECT_THAT(TEST_DATA::return_viber_msg,testing::HasSubstr("temperatura rośnie"));
343
1
    EXPECT_THAT(TEST_DATA::return_viber_msg,testing::HasSubstr("polu"));
344
1
}
345
346
TEST_F(iDomTOOLS_ClassTest, speakersON_OFF)
347
1
{
348
1
    EXPECT_EQ(test_status.getObjectState("speakers"), STATE::OFF);
349
1
    useful_F::myStaticData->idom_all_state.houseState = STATE::UNLOCK;
350
1
    test_idomTOOLS->turnOnSpeakers();
351
1
    EXPECT_EQ(test_status.getObjectState("speakers"), STATE::ON);
352
1
    test_idomTOOLS->turnOffSpeakers();
353
1
    EXPECT_EQ(test_status.getObjectState("speakers"), STATE::OFF);
354
1
    useful_F::myStaticData->idom_all_state.houseState = STATE::LOCK;
355
1
    test_idomTOOLS->turnOnSpeakers();
356
1
    EXPECT_EQ(test_status.getObjectState("speakers"), STATE::OFF);
357
1
    std::string retStr = useful_F::myStaticData->myEventHandler.run("speakers")->getEvent();
358
1
    EXPECT_THAT(retStr, testing::HasSubstr("speakers can not start due to home state: LOCK"));
359
1
}
360
361
TEST_F(iDomTOOLS_ClassTest, printerON_OFF)
362
1
{
363
1
    useful_F::myStaticData->idom_all_state.houseState = STATE::UNLOCK;
364
1
    test_idomTOOLS->turnOnPrinter();
365
1
    EXPECT_EQ(test_status.getObjectState("printer"), STATE::ON);
366
1
    test_idomTOOLS->turnOffPrinter();
367
1
    EXPECT_EQ(test_status.getObjectState("printer"), STATE::OFF);
368
1
    useful_F::myStaticData->idom_all_state.houseState = STATE::LOCK;
369
1
    test_idomTOOLS->turnOnPrinter();
370
1
    EXPECT_EQ(test_status.getObjectState("printer"), STATE::OFF);
371
1
    std::string retStr = useful_F::myStaticData->myEventHandler.run("230V")->getEvent();
372
1
    EXPECT_THAT(retStr, testing::HasSubstr("Printer can not start due to home state: LOCK"));
373
1
}
374
375
TEST_F(iDomTOOLS_ClassTest, getPinState)
376
1
{
377
1
    setReturnPinState(0);
378
1
    EXPECT_EQ(test_idomTOOLS->getPinState(0), PIN_STATE::LOW_STATE);
379
1
    setReturnPinState(1);
380
1
    EXPECT_EQ(test_idomTOOLS->getPinState(0), PIN_STATE::HIGH_STATE);
381
1
    setReturnPinState(4);
382
1
    EXPECT_EQ(test_idomTOOLS->getPinState(0), PIN_STATE::UNKNOWN_STATE);
383
1
}
384
385
TEST_F(iDomTOOLS_ClassTest, turnOnOffPrinter)
386
1
{
387
1
    useful_F::myStaticData->idom_all_state.houseState = STATE::UNLOCK;
388
1
    test_status.setObjectState("printer",STATE::ON);
389
1
    EXPECT_EQ(test_status.getObjectState("printer"), STATE::ON);
390
1
    setReturnPinState(1);
391
1
    puts("off printer");
392
1
    test_idomTOOLS->turnOnOffPrinter();
393
1
    EXPECT_EQ(test_status.getObjectState("printer"), STATE::OFF);
394
1
    setReturnPinState(0);
395
1
    puts("on printer");
396
1
    test_idomTOOLS->turnOnOffPrinter();
397
1
    EXPECT_EQ(test_status.getObjectState("printer"), STATE::ON);
398
1
    setReturnPinState(4);
399
1
    test_idomTOOLS->turnOnOffPrinter();
400
1
    EXPECT_EQ(test_status.getObjectState("printer"), STATE::ON);
401
1
}
402
403
TEST_F(iDomTOOLS_ClassTest, turn_On_Off_433MHzSwitch)
404
1
{
405
1
    useful_F::myStaticData->idom_all_state.houseState = STATE::UNLOCK;
406
1
    EXPECT_EQ(test_status.getObjectState("B"),STATE::UNKNOWN);
407
1
    test_idomTOOLS->turnOn433MHzSwitch("B");
408
1
    EXPECT_EQ(test_status.getObjectState("B"),STATE::ON);
409
1
    test_idomTOOLS->turnOff433MHzSwitch("B");
410
1
    EXPECT_EQ(test_status.getObjectState("B"),STATE::OFF);
411
1
}
412
413
TEST_F(iDomTOOLS_ClassTest, turnOnOff433MHzSwitch)
414
1
{
415
1
    useful_F::myStaticData->idom_all_state.houseState = STATE::UNLOCK;
416
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("B"),STATE::UNKNOWN);
417
1
    test_my_data.main_iDomStatus->setObjectState("B",STATE::ON);
418
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("B"),STATE::ON);
419
1
    test_idomTOOLS->turnOnOff433MHzSwitch("B");
420
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("B"),STATE::OFF);
421
1
    test_idomTOOLS->turnOnOff433MHzSwitch("B");
422
1
    EXPECT_EQ(test_status.getObjectState("B"),STATE::ON);
423
1
424
1
}
425
426
TEST_F(iDomTOOLS_ClassTest, runOnSunset)
427
1
{
428
1
    useful_F::myStaticData->idom_all_state.houseState = STATE::LOCK;
429
1
    test_idomTOOLS->runOnSunset();
430
1
    std::string retStr = useful_F::myStaticData->myEventHandler.run("iDom")->getEvent();
431
1
    EXPECT_THAT(retStr, testing::HasSubstr("433MHz can not start due to home state: LOCK"));
432
1
433
1
    useful_F::myStaticData->idom_all_state.houseState = STATE::UNLOCK;
434
1
    auto ptr = static_cast<RADIO_SWITCH*>(test_my_data.main_REC->getEqPointer("B"));
435
1
    ptr->m_state = STATE::ON;
436
1
    test_idomTOOLS->runOnSunset();
437
1
438
1
    EXPECT_EQ(test_my_data.main_REC->getEqPointer("B")->getState(), STATE::OFF);
439
1
440
1
    RADIO_EQ_CONFIG cfg;
441
1
    cfg.sunset = "on";
442
1
    cfg.sunrise = "off";
443
1
444
1
    ptr->setCode(cfg);
445
1
    ptr->m_state = STATE::OFF;
446
1
    test_idomTOOLS->runOnSunset();
447
1
448
1
    EXPECT_EQ(test_my_data.main_REC->getEqPointer("B")->getState(), STATE::ON);
449
1
}
450
451
TEST_F(iDomTOOLS_ClassTest, runOnSunrise)
452
1
{
453
1
    useful_F::myStaticData->idom_all_state.houseState = STATE::LOCK;
454
1
    test_idomTOOLS->runOnSunrise();
455
1
    std::string retStr = useful_F::myStaticData->myEventHandler.run("iDom")->getEvent();
456
1
    EXPECT_THAT(retStr, testing::HasSubstr("433MHz can not start due to home state: LOCK"));
457
1
458
1
    useful_F::myStaticData->idom_all_state.houseState = STATE::UNLOCK;
459
1
    auto ptr = static_cast<RADIO_SWITCH*>(test_my_data.main_REC->getEqPointer("B"));
460
1
    ptr->m_state = STATE::OFF;
461
1
    test_idomTOOLS->runOnSunrise();
462
1
463
1
    EXPECT_EQ(test_my_data.main_REC->getEqPointer("B")->getState(), STATE::ON);
464
1
465
1
    RADIO_EQ_CONFIG cfg;
466
1
    cfg.sunset = "off";
467
1
    cfg.sunrise = "on";
468
1
469
1
    ptr->setCode(cfg);
470
1
471
1
    cfg.sunset = "on";
472
1
    cfg.sunrise = "off";
473
1
474
1
    ptr->setCode(cfg);
475
1
    ptr->m_state = STATE::ON;
476
1
    test_idomTOOLS->runOnSunrise();
477
1
478
1
    EXPECT_EQ(test_my_data.main_REC->getEqPointer("B")->getState(), STATE::OFF);
479
1
}
480
481
TEST_F(iDomTOOLS_ClassTest, getSunrise_Sunset)
482
1
{
483
1
    std::string ret = test_idomTOOLS->getSunrise();
484
1
    EXPECT_THAT(ret, testing::HasSubstr(":"));
485
1
486
1
    ret = test_idomTOOLS->getSunset();
487
1
    EXPECT_THAT(ret, testing::HasSubstr(":"));
488
1
489
1
    ret = test_idomTOOLS->getSunrise(true);
490
1
    EXPECT_THAT(ret, testing::HasSubstr("Sunrise time:"));
491
1
492
1
    ret = test_idomTOOLS->getSunset(true);
493
1
    EXPECT_THAT(ret, testing::HasSubstr("Sunset time:"));
494
1
}
495
496
TEST_F(iDomTOOLS_ClassTest, getDayLenght)
497
1
{
498
1
    std::string ret = test_idomTOOLS->getDayLenght();
499
1
    EXPECT_THAT(ret, testing::HasSubstr(":"));
500
1
501
1
    ret = test_idomTOOLS->getDayLenght(true);
502
1
    EXPECT_THAT(ret, testing::HasSubstr("Day Lenght :"));
503
1
}
504
505
TEST_F(iDomTOOLS_ClassTest, getTextToSpeach)
506
1
{
507
1
    TEST_DATA::return_send_to_arduino = "22:23";
508
1
    std::string ret = test_idomTOOLS->getTextToSpeach();
509
1
    EXPECT_THAT(ret, testing::HasSubstr("Smog:"));
510
1
    std::cout << "TEXT :"<< std::endl << ret << std::endl;
511
1
}
512
513
TEST_F(iDomTOOLS_ClassTest, mpd)
514
1
{
515
1
    MPD_info test_ptr_MPD;
516
1
    test_ptr_MPD.volume = 3;
517
1
    test_my_data.ptr_MPD_info = &test_ptr_MPD;
518
1
    blockQueue test_q;
519
1
    test_q._clearAll();
520
1
    useful_F::myStaticData->idom_all_state.houseState = STATE::LOCK;
521
1
    test_idomTOOLS->MPD_play(&test_my_data);
522
1
    std::string retStr = useful_F::myStaticData->myEventHandler.run("MPD")->getEvent();
523
1
    EXPECT_THAT(retStr, testing::HasSubstr("MPD can not start due to home state: LOCK"));
524
1
    EXPECT_EQ(test_q._size(), 0);
525
1
526
1
    useful_F::myStaticData->idom_all_state.houseState = STATE::UNLOCK;
527
1
    test_idomTOOLS->MPD_play(&test_my_data);
528
1
    EXPECT_EQ(test_q._size(), 1);
529
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::PLAY);
530
1
    EXPECT_EQ(test_q._size(), 0);
531
1
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
532
1
    useful_F::myStaticData->idom_all_state.houseState = STATE::LOCK;
533
1
534
1
    useful_F::myStaticData->myEventHandler.run("MPD")->clearEvent();
535
1
    test_idomTOOLS->MPD_play(&test_my_data,2);
536
1
    retStr = useful_F::myStaticData->myEventHandler.run("MPD")->getEvent();
537
1
    EXPECT_THAT(retStr, testing::HasSubstr("MPD can not start due to home state: LOCK"));
538
1
    EXPECT_EQ(test_q._size(), 0);
539
1
540
1
    useful_F::myStaticData->idom_all_state.houseState = STATE::UNLOCK;
541
1
    test_idomTOOLS->MPD_play(&test_my_data,2);
542
1
    EXPECT_EQ(test_q._size(), 1);
543
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::PLAY_ID);
544
1
    EXPECT_EQ(test_q._size(), 0);
545
1
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
546
1
547
1
    test_idomTOOLS->MPD_stop();
548
1
    EXPECT_EQ(test_q._size(), 1);
549
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::STOP);
550
1
    EXPECT_EQ(test_q._size(), 0);
551
1
552
1
    test_idomTOOLS->MPD_next();
553
1
    EXPECT_EQ(test_q._size(), 1);
554
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::NEXT);
555
1
    EXPECT_EQ(test_q._size(), 0);
556
1
557
1
    test_idomTOOLS->MPD_prev();
558
1
    EXPECT_EQ(test_q._size(), 1);
559
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::PREV);
560
1
    EXPECT_EQ(test_q._size(), 0);
561
1
562
1
    test_idomTOOLS->MPD_pause();
563
1
    EXPECT_EQ(test_q._size(), 1);
564
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::PAUSE );
565
1
    EXPECT_EQ(test_q._size(), 0);
566
1
567
1
    test_idomTOOLS->MPD_volumeUp();
568
1
    EXPECT_EQ(test_q._size(), 1);
569
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::VOLUP );
570
1
    EXPECT_EQ(test_q._size(), 0);
571
1
572
1
    test_idomTOOLS->MPD_volumeDown();
573
1
    EXPECT_EQ(test_q._size(), 1);
574
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::VOLDOWN );
575
1
    EXPECT_EQ(test_q._size(), 0);
576
1
577
1
    test_idomTOOLS->MPD_volumeSet(&test_my_data, 99);
578
1
    EXPECT_EQ(test_q._size(), 1);
579
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::VOLSET );
580
1
    EXPECT_EQ(test_q._size(), 0);
581
1
    EXPECT_EQ(test_my_data.ptr_MPD_info->volume, 99);
582
1
583
1
    EXPECT_EQ(test_idomTOOLS->MPD_getVolume(&test_my_data),99);
584
1
585
1
}
586
587
TEST_F(iDomTOOLS_ClassTest, getTemperatureString)
588
1
{
589
1
    TEST_DATA::return_send_to_arduino = "-2:2";
590
1
    EXPECT_STREQ(test_my_data.main_iDomTools->getTemperatureString().c_str(), "-2:2");
591
1
}
592
593
TEST_F(iDomTOOLS_ClassTest, cameraLED)
594
1
{
595
1
    TEST_DATA::return_httpPost = "ok.\n";
596
1
    test_my_data.main_iDomTools->cameraLedOFF("test_link");
597
1
598
1
    ///////////////////////////////at day
599
1
    Clock::setTime_forBT_usage(12,12);
600
1
    test_my_data.main_iDomTools->cameraLedON("test_link");
601
1
602
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("cameraLED"), STATE::OFF);
603
1
    ////////////////////////////////////// at night
604
1
    Clock::setTime_forBT_usage(2,2);
605
1
    test_my_data.main_iDomTools->cameraLedON("test_link");
606
1
607
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("cameraLED"), STATE::ON);
608
1
}
609
610
TEST_F(iDomTOOLS_ClassTest, textToSpeach)
611
1
{
612
1
    test_my_data.ptr_MPD_info->isPlay = true;
613
1
    test_my_data.main_iDomStatus->setObjectState("speakers", STATE::UNDEFINE);
614
1
615
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("speakers"), STATE::UNDEFINE);
616
1
    std::vector<std::string> test_v;
617
1
    test_my_data.main_iDomTools->textToSpeach(&test_v); //empty
618
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("speakers"), STATE::UNDEFINE);
619
1
620
1
    test_v = {"test","msg","clock"};
621
1
    test_my_data.ptr_MPD_info->isPlay = true;
622
1
    test_my_data.main_iDomTools->textToSpeach(&test_v);
623
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("speakers"), STATE::UNDEFINE);
624
1
    test_my_data.ptr_MPD_info->isPlay = false;
625
1
    test_my_data.main_iDomTools->textToSpeach(&test_v);
626
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("speakers"), STATE::OFF);
627
1
}
628
629
TEST_F(iDomTOOLS_ClassTest, getWeatherEvent)
630
1
{
631
1
    TEST_DATA::return_httpPost = "httpPost";
632
1
    std::string retStr = test_my_data.main_iDomTools->getWeatherEvent("test",10);
633
1
    EXPECT_STREQ(retStr.c_str(),"httpPost");
634
1
}
635
636
TEST_F(iDomTOOLS_ClassTest, isItDay)
637
1
{
638
1
    Clock::setTime_forBT_usage(12,12);
639
1
    EXPECT_TRUE(test_my_data.main_iDomTools->isItDay());
640
1
    Clock::setTime_forBT_usage(2,12);
641
1
    EXPECT_FALSE(test_my_data.main_iDomTools->isItDay());
642
1
}
643
644
TEST_F(iDomTOOLS_ClassTest, ledClear)
645
1
{
646
1
    TEST_DATA::return_send_to_arduino = "done";
647
1
    std::string retStr = test_my_data.main_iDomTools->ledClear();
648
1
    EXPECT_STREQ(retStr.c_str(),"done");
649
1
}
650
651
TEST_F(iDomTOOLS_ClassTest, getAllDataSunrisesunset)
652
1
{
653
    EXPECT_THAT(test_my_data.main_iDomTools->getAllDataSunrisesunset(),
654
                testing::HasSubstr("Days until Y2K"));
655
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDomTools/idomtools.cpp
Line
Count
Source (jump to first uncovered line)
1
#include <algorithm>
2
#include <fstream>
3
#include <string>
4
#include <typeinfo>
5
6
#include "idomtools.h"
7
#include "../functions/functions.h"
8
#include "../../libs/emoji/emoji.h"
9
#include "../../libs/Statistic/statistic.h"
10
#include "../CRON/cron.hpp"
11
#include "../RADIO_433_eq/radio_433_eq.h"
12
#include "json.hpp"
13
#include "../thread_functions/iDom_thread.h"
14
15
iDomTOOLS::iDomTOOLS(thread_data *myData): key(myData->server_settings->TS_KEY)
16
192
{
17
192
    puts("iDomTOOLS::iDomTOOLS()");
18
192
    my_data = myData;
19
192
20
192
    //////////////////////////////////// temeprature /////////////////
21
192
22
192
    allThermometer.add("inside");
23
192
    allThermometer.add("outside");
24
192
    allThermometerUpdate.add("inside");
25
192
    allThermometerUpdate.add("outside");
26
192
    /////////////////////////////////////////////////////////////////
27
#ifndef BT_TEST
28
    pinMode(iDomConst::GPIO_SPIK, OUTPUT); // gpio pin do zasilania glosnikow
29
    digitalWrite(iDomConst::GPIO_SPIK,LOW);
30
    pinMode(iDomConst::GPIO_PRINTER,OUTPUT); /// gpio pin do zsilania drukarki
31
    digitalWrite(iDomConst::GPIO_PRINTER,LOW);
32
    pinMode(iDomConst::BUTTON_PIN, INPUT); // gpio pin przycisku
33
34
    if (wiringPiISR (iDomConst::BUTTON_PIN, INT_EDGE_BOTH, &useful_F::button_interrupt) < 0 ) {
35
36
        log_file_cout.mutex_lock();
37
        log_file_cout << CRITICAL <<"Unable to setup ISR RISING "<<std::endl;
38
        log_file_cout.mutex_unlock();
39
40
    }
41
#endif
42
    my_data->main_iDomStatus->addObject("cameraLED",STATE::UNKNOWN);
43
192
    my_data->main_iDomStatus->addObject("printer",STATE::OFF);
44
192
    my_data->main_iDomStatus->addObject("speakers",STATE::OFF);
45
192
    my_data->main_iDomStatus->addObject("alarm",STATE::DEACTIVE);
46
192
    my_data->main_iDomStatus->addObject("KODI",STATE::DEACTIVE);
47
192
48
192
    ///////// setup viber api
49
192
    m_viber.setAvatar(my_data->server_settings->viberAvatar);
50
192
    m_viber.setAccessToken(my_data->server_settings->viberToken);
51
192
    m_viber.setURL("https://chatapi.viber.com/pa/send_message");
52
192
    ///////// setup faceboook api
53
192
    m_facebook.setAccessToken(my_data->server_settings->facebookAccessToken);
54
192
55
192
    //////// button 433MHz
56
192
    buttonPointerVector = my_data->main_REC->getButtonPointerVector();
57
192
58
192
    lastButton433MHzLockUnlockTime = Clock::getTime() + Clock(23,58);
59
192
60
192
}
61
62
TEMPERATURE_STATE iDomTOOLS::hasTemperatureChange(const std::string& thermometerName, double reference, double histereza )
63
16
{
64
16
    reference += 0.0055;
65
16
    const auto newTemp = allThermometer.getTemp(thermometerName);
66
16
    const auto oldTemp = allThermometer.getOldTemp(thermometerName);
67
16
    const auto lastState = allThermometer.getLastState(thermometerName);
68
16
    if (newTemp >= reference + histereza &&
69
16
            oldTemp < reference + histereza &&
70
16
            lastState != TEMPERATURE_STATE::Over)
71
3
    {
72
3
        my_data->myEventHandler.run("test")->addEvent("over: new "+ to_string_with_precision(newTemp)+" old: "
73
3
                                                      +to_string_with_precision(oldTemp)+" ref: "
74
3
                                                      +to_string_with_precision(reference));
75
3
        allThermometer.setState(thermometerName, TEMPERATURE_STATE::Over);
76
3
        return TEMPERATURE_STATE::Over;
77
3
    }
78
13
    else if (newTemp <= reference - histereza &&
79
13
             oldTemp > reference - histereza &&
80
13
             lastState != TEMPERATURE_STATE::Under)
81
3
    {
82
3
        my_data->myEventHandler.run("test")->addEvent("under: new "+to_string_with_precision(newTemp)+" old: "
83
3
                                                      +to_string_with_precision(oldTemp)+" ref: "
84
3
                                                      +to_string_with_precision(reference));
85
3
        allThermometer.setState(thermometerName, TEMPERATURE_STATE::Under);
86
3
        return TEMPERATURE_STATE::Under;
87
3
    }
88
10
89
10
    my_data->myEventHandler.run("test")->addEvent("noChanges: new "+to_string_with_precision(newTemp)+" old: "
90
10
                                                  +to_string_with_precision(oldTemp)+" ref: "+to_string_with_precision(reference));
91
10
92
10
    allThermometer.setState(thermometerName, TEMPERATURE_STATE::NoChanges);
93
10
    return TEMPERATURE_STATE::NoChanges;
94
10
}
95
96
void iDomTOOLS::sendSMSifTempChanged(const std::string& thermomethernName, int reference)
97
16
{
98
16
    TEMPERATURE_STATE status = hasTemperatureChange(thermomethernName,reference,0.5);
99
16
    std::string m = "temperature "+thermomethernName+" over "+ EMOJI::emoji(E_emoji::NORTH_EAST_ARROW)
100
16
            + to_string_with_precision(reference);
101
16
102
16
    if (status == TEMPERATURE_STATE::Over){
103
3
        my_data->myEventHandler.run("temperature")->addEvent(m);
104
3
        if (reference < 2){
105
1
            sendViberMsg(m,my_data->server_settings->viberReceiver.at(0),my_data->server_settings->viberSender);
106
1
            sendViberMsg(m,my_data->server_settings->viberReceiver.at(1),my_data->server_settings->viberSender);
107
1
        }
108
2
        else{
109
2
            sendViberMsg(m,my_data->server_settings->viberReceiver.at(0),my_data->server_settings->viberSender);
110
2
        }
111
3
    }
112
13
    else if (status == TEMPERATURE_STATE::Under){
113
3
        m ="temperature " + thermomethernName+" under "+EMOJI::emoji(E_emoji::SOUTH_EAST_ARROW)
114
3
                +to_string_with_precision(reference);
115
3
        my_data->myEventHandler.run("temperature")->addEvent(m);
116
3
        if (reference < 2){
117
2
            sendViberPicture(m,"http://canacopegdl.com/images/cold/cold-14.jpg",
118
2
                             my_data->server_settings->viberReceiver.at(0),
119
2
                             my_data->server_settings->viberSender);
120
2
            sendViberPicture(m,"http://canacopegdl.com/images/cold/cold-14.jpg",
121
2
                             my_data->server_settings->viberReceiver.at(1),
122
2
                             my_data->server_settings->viberSender);
123
2
            postOnFacebook(m,"http://canacopegdl.com/images/cold/cold-14.jpg");
124
2
        }
125
1
        else {
126
1
            sendViberMsg(m,my_data->server_settings->viberReceiver.at(0),
127
1
                         my_data->server_settings->viberSender);
128
1
        }
129
3
    }
130
10
    else{
131
10
        //my_data->myEventHandler.run("unknown")->addEvent("temperatura nie przeszla przez "+to_string_with_precision(reference));
132
10
    }
133
16
}
134
135
std::string iDomTOOLS::getThermoStats(const std::string& name)
136
2
{
137
2
    return allThermometerUpdate.getStatsByName(name);
138
2
}
139
140
void iDomTOOLS::updateTemperatureStats()
141
6
{
142
6
    auto v = getTemperature();
143
6
    allThermometerUpdate.updateAll(&v);
144
6
    allThermometerUpdate.updateStats("outside");
145
6
    allThermometerUpdate.updateStats("inside");
146
6
147
6
    if( true == allThermometerUpdate.isMoreDiff("outside",2.1)){
148
2
        auto data = allThermometerUpdate.getLast2("outside");
149
2
        std::string msg = "alarm roznicy temeratur na polu! " + to_string_with_precision(data.first) +" na "+
150
2
                to_string_with_precision(data.second);
151
2
152
2
        if (data.first > data.second){
153
1
            msg += " temperatura maleje " + EMOJI::emoji(E_emoji::CHART_WITH_DOWNWARDS_TREND);
154
1
        }
155
1
        else{
156
1
            msg += " temperatura rośnie " + EMOJI::emoji(E_emoji::CHART_WITH_UPWARDS_TREND);
157
1
        }
158
2
159
2
        sendViberMsg(msg,
160
2
                     my_data->server_settings->viberReceiver.at(0),
161
2
                     my_data->server_settings->viberSender);
162
2
163
2
        log_file_mutex.mutex_lock();
164
2
        log_file_cout << WARNING << msg << std::endl;
165
2
        log_file_mutex.mutex_unlock();
166
2
    }
167
6
    if( true == allThermometerUpdate.isMoreDiff("inside",2.1)){
168
2
        auto data = allThermometerUpdate.getLast2("inside");
169
2
        std::string msg = "alarm roznicy temeratur na mieszkaniu! " + to_string_with_precision(data.first) +" na "+
170
2
                to_string_with_precision(data.second);
171
2
172
2
        if (data.first > data.second){
173
1
            msg += " temperatura maleje " + EMOJI::emoji(E_emoji::CHART_WITH_DOWNWARDS_TREND);
174
1
        }
175
1
        else{
176
1
            msg += " temperatura rośnie " + EMOJI::emoji(E_emoji::CHART_WITH_UPWARDS_TREND);
177
1
        }
178
2
179
2
        sendViberMsg(msg,
180
2
                     my_data->server_settings->viberReceiver.at(0),
181
2
                     my_data->server_settings->viberSender);
182
2
183
2
        log_file_mutex.mutex_lock();
184
2
        log_file_cout << WARNING << msg << std::endl;
185
2
        log_file_mutex.mutex_unlock();
186
2
    }
187
6
}
188
189
void iDomTOOLS::turnOnSpeakers()
190
8
{
191
8
    if (useful_F::myStaticData->idom_all_state.houseState == STATE::UNLOCK)
192
4
    {
193
4
        digitalWrite(iDomConst::GPIO_SPIK, HIGH);
194
4
        useful_F::myStaticData->main_iDomStatus->setObjectState("speakers",STATE::ON);
195
4
    }
196
4
    else{
197
4
        useful_F::myStaticData->myEventHandler.run("speakers")->addEvent("speakers can not start due to home state: "+
198
4
                                                                         stateToString(useful_F::myStaticData->idom_all_state.houseState));
199
4
    }
200
8
    useful_F::myStaticData->main_iDomTools->saveState_iDom();
201
8
}
202
203
void iDomTOOLS::turnOffSpeakers()
204
6
{
205
6
    digitalWrite(iDomConst::GPIO_SPIK, LOW);
206
6
    useful_F::myStaticData->main_iDomStatus->setObjectState("speakers",STATE::OFF);
207
6
    // useful_F::myStaticData->main_iDomTools->saveState_iDom();
208
6
}
209
210
void iDomTOOLS::turnOnPrinter()
211
5
{
212
5
    if (my_data->idom_all_state.houseState == STATE::UNLOCK)
213
4
    {
214
4
        digitalWrite(iDomConst::GPIO_PRINTER,HIGH);
215
4
        my_data->myEventHandler.run("230V")->addEvent("230v drukarki ON");
216
4
        my_data->main_iDomStatus->setObjectState("printer",STATE::ON);
217
4
    }
218
1
    else{
219
1
        my_data->myEventHandler.run("230V")->addEvent("Printer can not start due to home state: "+
220
1
                                                      stateToString(my_data->idom_all_state.houseState));
221
1
    }
222
5
}
223
224
void iDomTOOLS::turnOffPrinter()
225
6
{
226
6
    digitalWrite(iDomConst::GPIO_PRINTER,LOW);
227
6
    my_data->myEventHandler.run("230V")->addEvent("230v drukarki OFF");
228
6
    my_data->main_iDomStatus->setObjectState("printer",STATE::OFF);
229
6
}
230
231
PIN_STATE iDomTOOLS::getPinState(int pin_number)
232
7
{
233
7
    int pin_state = digitalRead(pin_number);
234
7
    switch (pin_state){
235
7
    case 0:
236
3
        return PIN_STATE::LOW_STATE;
237
7
    case 1:
238
2
        return PIN_STATE::HIGH_STATE;
239
7
    default:
240
2
        return PIN_STATE::UNKNOWN_STATE;
241
0
    }
242
0
}
243
244
void iDomTOOLS::turnOnOffPrinter()
245
4
{
246
4
    PIN_STATE pinState = getPinState(iDomConst::GPIO_PRINTER);
247
4
    switch (pinState){
248
4
    case PIN_STATE::HIGH_STATE:
249
1
        turnOffPrinter();
250
1
        my_data->mainLCD->set_lcd_STATE(10);
251
1
        my_data->mainLCD->printString(true,0,0,"230V OFF");
252
1
        break;
253
4
    case PIN_STATE::LOW_STATE:
254
2
        turnOnPrinter();
255
2
        my_data->mainLCD->set_lcd_STATE(10);
256
2
        my_data->mainLCD->printString(true,0,0,"230V ON");
257
2
        break;
258
4
    default:
259
1
        puts("def");
260
1
261
1
        log_file_mutex.mutex_lock();
262
1
        log_file_cout << CRITICAL << " blad odczytu stanu pinu zasilania drukarki "<< std::endl;
263
1
        log_file_mutex.mutex_unlock();
264
4
    }
265
4
}
266
267
void iDomTOOLS::turnOnOff433MHzSwitch(const std::string& name)
268
4
{
269
4
    STATE listwaState = my_data->main_iDomStatus->getObjectState(name);
270
4
    RADIO_SWITCH *m_switch = dynamic_cast<RADIO_SWITCH*>(my_data->main_REC->getEqPointer(name));
271
4
    if (listwaState == STATE::ON){
272
2
        my_data->mainLCD->set_lcd_STATE(10);
273
2
        my_data->mainLCD->printString(true,0,0,"230V OFF "+name);
274
2
        m_switch->off();
275
2
    }
276
2
    else if (listwaState == STATE::OFF){
277
2
        my_data->mainLCD->set_lcd_STATE(10);
278
2
        my_data->mainLCD->printString(true,0,0,"230V ON "+name);
279
2
        m_switch->on();
280
2
    }
281
4
    saveState_iDom();
282
4
}
283
284
void iDomTOOLS::turnOn433MHzSwitch(std::string name)
285
1
{
286
1
    RADIO_SWITCH *m_switch = dynamic_cast<RADIO_SWITCH*>(my_data->main_REC->getEqPointer(std::move(name)));
287
1
    m_switch->on();
288
1
    //saveState_iDom();
289
1
}
290
291
void iDomTOOLS::turnOff433MHzSwitch(std::string name)
292
4
{
293
4
    RADIO_SWITCH *m_switch = dynamic_cast<RADIO_SWITCH*>(my_data->main_REC->getEqPointer(std::move(name)));
294
4
    m_switch->off();
295
4
}
296
297
void iDomTOOLS::runOnSunset()
298
3
{
299
3
    if (my_data->idom_all_state.houseState == STATE::UNLOCK)
300
2
    {
301
2
        ////switch 433mhz
302
10
        for (auto m_switch : my_data->main_REC->getSwitchPointerVector()){
303
10
            m_switch->onSunset();
304
10
        }
305
2
    }
306
1
    else{
307
1
        my_data->myEventHandler.run("iDom")->addEvent("433MHz can not start due to home state: "+
308
1
                                                      stateToString(my_data->idom_all_state.houseState));
309
1
    }
310
3
}
311
312
void iDomTOOLS::runOnSunrise()
313
4
{
314
4
    if (my_data->idom_all_state.houseState == STATE::UNLOCK)
315
2
    {
316
2
        ////switch 433mhz
317
10
        for (auto m_switch : my_data->main_REC->getSwitchPointerVector()){
318
10
            m_switch->onSunrise();
319
10
        }
320
2
    }
321
2
    else{
322
2
        my_data->myEventHandler.run("iDom")->addEvent("433MHz can not start due to home state: "+
323
2
                                                      stateToString(my_data->idom_all_state.houseState));
324
2
    }
325
4
    my_data->main_iDomTools->ledOFF();
326
4
}
327
328
void iDomTOOLS::lockHome()
329
7
{
330
7
    my_data->idom_all_state.houseState = STATE::LOCK;
331
7
    my_data->main_iDomStatus->setObjectState("house", STATE::LOCK);
332
7
    my_data->main_iDomTools->sendViberPicture("dom zablokownay!",
333
7
                                              "http://cyniu88.no-ip.pl/images/iDom/iDom/lock.jpg",
334
7
                                              my_data->server_settings->viberReceiver.at(0),
335
7
                                              my_data->server_settings->viberSender);
336
7
337
7
    log_file_mutex.mutex_lock();
338
7
    log_file_cout << INFO << "status domu - "+stateToString(my_data->idom_all_state.houseState)<< std::endl;
339
7
    log_file_mutex.mutex_unlock();
340
7
341
7
    saveState_iDom();
342
7
}
343
344
void iDomTOOLS::unlockHome()
345
14
{
346
14
    my_data->idom_all_state.houseState = STATE::UNLOCK;
347
14
    my_data->main_iDomStatus->setObjectState("house", STATE::UNLOCK);
348
14
    my_data->main_iDomTools->sendViberPicture("dom odblokownay!",
349
14
                                              "http://cyniu88.no-ip.pl/images/iDom/iDom/unlock.jpg",
350
14
                                              my_data->server_settings->viberReceiver.at(0),
351
14
                                              my_data->server_settings->viberSender);
352
14
353
14
    log_file_mutex.mutex_lock();
354
14
    log_file_cout << INFO << "status domu - "+stateToString(my_data->idom_all_state.houseState)<< std::endl;
355
14
    log_file_mutex.mutex_unlock();
356
14
357
14
    saveState_iDom();
358
14
}
359
360
void iDomTOOLS::switchActionOnLockHome()
361
1
{
362
1
    ////switch 433mhz
363
5
    for (auto m_switch : my_data->main_REC->getSwitchPointerVector()){
364
5
        m_switch->onLockHome();
365
5
    }
366
1
}
367
368
void iDomTOOLS::switchActionOnUnlockHome()
369
1
{
370
1
    ////switch 433mhz
371
5
    for (auto m_switch : my_data->main_REC->getSwitchPointerVector()){
372
5
        m_switch->onUnlockHome();
373
5
    }
374
1
}
375
376
std::string iDomTOOLS::buttonPressed(const std::string& id)
377
2
{
378
2
    for (auto n : buttonPointerVector){
379
2
        if (id == n->getID()){
380
1
            return n->getName();
381
1
        }
382
1
    }
383
1
    throw "UNKNOWN BUTTON ID: " + std::to_string(id);
384
1
}
385
386
void iDomTOOLS::button433MHzPressedAction(const std::string& name)
387
4
{
388
4
    if (name == "locker"){
389
4
        RADIO_BUTTON* buttonLocker = static_cast<RADIO_BUTTON*>(my_data->main_REC->getEqPointer(name) );
390
4
        button433mhzLockerPressed(buttonLocker);
391
4
    }
392
4
}
393
394
void iDomTOOLS::button433mhzLockerPressed(RADIO_BUTTON *radioButton)
395
10
{
396
10
    static unsigned int counter = 0;
397
10
398
10
    Clock t = Clock::getTime();
399
10
    if (lastButton433MHzLockUnlockTime != t /*|| (lastButton433MHzLockUnlockTime + Clock(0,1)) == t*/)
400
6
    {
401
6
#ifdef BT_TEST
402
6
        std::cout << "LOCKER TEST iDomTOOLS::button433mhzLockerPressed()" <<std::endl;
403
6
#endif
404
6
        lastButton433MHzLockUnlockTime = t;
405
6
        counter = 0;
406
6
        if(my_data->idom_all_state.houseState != STATE::UNLOCK)
407
2
        {
408
2
            buttonUnlockHome();
409
2
            puts("\nodblokuje dom\n");
410
2
            radioButton->setState(STATE::UNLOCK);
411
2
        }
412
4
        else if (my_data->main_iDomStatus->getObjectState("music") == STATE::PLAY)
413
1
        {
414
1
            ledOFF();
415
1
            MPD_stop();
416
1
            turnOffPrinter();
417
1
            radioButton->setState(STATE::STOP);
418
1
            switchActionOnLockHome();
419
1
            //TODO dodać wylaczanie wiatraka
420
1
        }
421
3
        else if (my_data->main_iDomStatus->getObjectState("music") == STATE::STOP)
422
1
        {
423
1
            MPD_play(my_data);
424
1
            switchActionOnUnlockHome();
425
1
            if(isItDay() == false)
426
1
            {
427
1
                ledOn(my_data->ptr_pilot_led->colorLED[2]);
428
1
            }
429
1
            radioButton->setState(STATE::PLAY);
430
1
        }
431
6
    }
432
4
    else
433
4
    {
434
4
        ++counter;
435
4
        if (counter == 2)
436
2
        {
437
2
            buttonLockHome();
438
2
            puts("\nzablokuje dom\n");
439
2
            radioButton->setState(STATE::LOCK);
440
2
        }
441
4
        //#ifdef BT_TEST
442
4
        std::cout << "LOCKER TEST iDomTOOLS::button433mhzLockerPressed()- counter: "<<counter <<std::endl;
443
4
        //#endif
444
4
    }
445
10
446
10
}
447
448
void iDomTOOLS::buttonLockHome()
449
2
{
450
2
    ledOFF();
451
2
    MPD_stop();
452
2
    turnOffPrinter();
453
2
    lockHome();
454
2
}
455
456
void iDomTOOLS::buttonUnlockHome()
457
2
{
458
2
    unlockHome();
459
2
    MPD_play(my_data);
460
2
    if(isItDay() == false){
461
2
        ledOn(my_data->ptr_pilot_led->colorLED[2]);
462
2
    }
463
2
}
464
465
bool iDomTOOLS::isItDay()
466
15
{
467
15
    Clock now = Clock::getTime();
468
15
    if(now < iDomTOOLS::getSunriseClock() || now > iDomTOOLS::getSunsetClock()){
469
14
        return false;
470
14
    }
471
1
    return true;
472
1
}
473
474
std::string iDomTOOLS::getAllDataSunrisesunset()
475
1
{
476
1
    return sun.getAllData();
477
1
}
478
479
CARDINAL_DIRECTIONS::ALARM_INFO iDomTOOLS::getLightningStruct()
480
4
{
481
4
    std::lock_guard<std::mutex> lock(m_lightningMutex);
482
4
    return m_lightningStruct;
483
4
}
484
485
void iDomTOOLS::setLightningStruct(CARDINAL_DIRECTIONS::ALARM_INFO &s)
486
2
{
487
2
    std::lock_guard<std::mutex> lock(m_lightningMutex);
488
2
    //std::cout <<"struktura setowana " << s.data.str() <<std::endl;
489
2
    m_lightningStruct = s;
490
2
491
2
    //std::cout <<"struktura już po setowaniu " << m_lightningStruct.data.str() <<std::endl;
492
2
}
493
494
void iDomTOOLS::checkLightning()
495
1
{
496
1
    nlohmann::json jj = useful_F_libs::getJson(my_data->server_settings->lightningApiURL);
497
1
498
1
    CARDINAL_DIRECTIONS::ALARM_INFO lightningData = lightning.lightningAlert(jj);
499
1
    setLightningStruct(lightningData);
500
1
    bool result = lightning.checkLightningAlert(&lightningData);
501
1
502
1
    if(result == true)
503
1
    {
504
1
505
1
        m_viber.setAvatar("http://cyniu88.no-ip.pl/avatar/lightning.jpg");
506
1
        STATE stateMSG = sendViberMsgBool("UWAGA BURZA KOŁO KRAKOWA! "+EMOJI::emoji(E_emoji::THUNDER_CLOUD_AND_RAIN)
507
1
                                          +"\\n\\n "+lightningData.data.str() ,
508
1
                                          my_data->server_settings->viberReceiver.at(0),
509
1
                                          my_data->server_settings->viberSender);
510
1
511
1
        if(stateMSG == STATE::SEND_NOK){
512
1
            log_file_mutex.mutex_lock();
513
1
            log_file_cout << ERROR << "nie wysłano informacje o burzy"<< std::endl;
514
1
            log_file_mutex.mutex_unlock();
515
1
        }
516
1
        stateMSG = sendViberMsgBool("UWAGA BURZA KOŁO KRAKOWA! "+EMOJI::emoji(E_emoji::THUNDER_CLOUD_AND_RAIN)
517
1
                                    +"\\n\\n "+lightningData.data.str() ,
518
1
                                    my_data->server_settings->viberReceiver.at(1),
519
1
                                    my_data->server_settings->viberSender);
520
1
521
1
        m_viber.setAvatar(my_data->server_settings->viberAvatar);
522
1
        if(stateMSG == STATE::SEND_OK)
523
0
        {
524
0
            log_file_mutex.mutex_lock();
525
0
            log_file_cout << INFO << "wysłano informacje o burzy"<< std::endl;
526
0
            log_file_mutex.mutex_unlock();
527
0
        }
528
1
        else
529
1
        {
530
1
            log_file_mutex.mutex_lock();
531
1
            log_file_cout << ERROR << "nie wysłano informacje o burzy"<< std::endl;
532
1
            log_file_mutex.mutex_unlock();
533
1
        }
534
1
    }
535
1
}
536
537
std::string iDomTOOLS::getSunrise(bool extend )
538
7
{
539
7
    Clock tt = sun.getSunRise();
540
7
    if (extend == true){
541
3
        return "Sunrise time: "+tt.getString();
542
3
    }
543
4
    return tt.getString();
544
4
}
545
546
std::string iDomTOOLS::getSunset(bool extend )
547
7
{
548
7
    Clock tt = sun.getSunSet();
549
7
    if (extend == true){
550
3
        return "Sunset time: "+tt.getString();
551
3
    }
552
4
    return tt.getString();
553
4
}
554
555
Clock iDomTOOLS::getSunsetClock()
556
1
{
557
1
    return sun.getSunSet();
558
1
}
559
560
Clock iDomTOOLS::getSunriseClock()
561
15
{
562
15
    return sun.getSunRise();
563
15
}
564
565
std::string iDomTOOLS::getDayLenght(bool extend )
566
7
{
567
7
    Clock tt = sun.getDayLength();
568
7
    if (extend == true){
569
3
        return "Day Lenght : "+tt.getString();
570
3
    }
571
4
    return tt.getString();
572
4
}
573
574
std::string iDomTOOLS::getWeatherEvent(const std::string& city, unsigned int radius)
575
1
{
576
1
    std::string url = "http://burze.dzis.net/ramka.php?miejscowosc=";
577
1
    url.append(city);
578
1
    url.append("&promien=");
579
1
    url.append(std::to_string(radius));
580
1
    return useful_F_libs::httpPost(url, 10);
581
1
}
582
583
std::vector<WEATHER_ALER> iDomTOOLS::getAlert(std::string data)
584
1
{
585
1
    std::vector<WEATHER_ALER> wAlert;
586
1
    WEATHER_ALER tempWA;
587
1
    std::string d = useful_F_libs::removeHtmlTag(data);
588
1
    std::vector<std::string> vect;
589
1
590
1
    vect = useful_F::split(d,'\n');
591
1
    vect.pop_back();
592
1
    for (auto n : vect)
593
7
    {
594
7
        if (n.find("brak") == std::string::npos)
595
1
        {
596
1
            tempWA.alert = n;
597
1
            tempWA.name = n;
598
1
            tempWA.sended = false;
599
1
            wAlert.push_back(tempWA);
600
1
        }
601
7
    }
602
1
    return {wAlert};
603
1
}
604
605
void iDomTOOLS::textToSpeach(std::vector<std::string> *textVector)
606
4
{
607
4
    if (textVector->empty() ){
608
1
        return;
609
1
    }
610
3
    std::string txt;
611
3
612
7
    for (auto a : *textVector){
613
7
        txt += a;
614
7
    }
615
3
    /////////// start thread TTS - python use ////////////////////////
616
3
    std::string command = " python /home/pi/programowanie/iDom_server_OOP/script/PYTHON/gadacz.py \\"+ txt +"\\";
617
3
    if(my_data->ptr_MPD_info->isPlay){
618
1
619
1
    }
620
2
    else {
621
2
        turnOnSpeakers();
622
2
    }
623
3
624
3
    useful_F::runLinuxCommand(command.c_str());
625
3
626
3
    if(my_data->ptr_MPD_info->isPlay){
627
1
628
1
    }
629
2
    else {
630
2
        turnOffSpeakers();
631
2
    }
632
3
}
633
634
std::string iDomTOOLS::getTextToSpeach()
635
3
{
636
3
    std::vector<std::string> dayL = useful_F::split(getDayLenght(),':');
637
3
    std::stringstream text;
638
3
    std::string smogText = getSmog();
639
3
    int smogInt = std::stoi(smogText);
640
3
    text << "Godzina: " << Clock::getTime().getString();
641
3
    text << ". \nWschód słońca: " << getSunrise();
642
3
    text << ". \nZachód słońca: " << getSunset();
643
3
    text << ". \nDługość dnia: " << dayL[0] << " godzin " << dayL[1] << " minut";
644
3
    text <<". \n";
645
3
    dayL = getTemperature();
646
3
    text << "Temperatura na zewnątrz: " << dayL[1] << " stopnia. \n";
647
3
    text << "Temperatura w pokoju: " << dayL[0] << " stopnia. \n";
648
3
    text << "Smog: " << smogText << " mg/m^3. \n";
649
3
    if (smogInt > 50){
650
0
        int result = smogInt *2;
651
0
        text << "UWAGA! Maksymalna wartość przekroczona " << result << "%.";
652
0
    }
653
3
    return text.str();
654
3
}
655
656
std::vector<std::string> iDomTOOLS::getTemperature()
657
18
{
658
18
    std::vector<std::string> vect = useful_F::split(useful_F::send_to_arduino(my_data,"temperature:22;"),':');
659
18
    return vect;
660
18
}
661
662
std::string iDomTOOLS::getTemperatureString()
663
2
{
664
2
    return useful_F::send_to_arduino(my_data,"temperature:22;");
665
2
}
666
667
std::string iDomTOOLS::getSmog()
668
14
{
669
14
    CURL *curl;
670
14
    CURLcode res;
671
14
    std::string readBuffer;
672
14
    curl = curl_easy_init();
673
14
674
14
    if(curl) {
675
14
        curl_easy_setopt(curl, CURLOPT_URL, "www.smog.krakow.pl");
676
14
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, useful_F_libs::WriteCallback);
677
14
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
678
14
        res = curl_easy_perform(curl);
679
14
        /* Check for errors */
680
14
        if(res != CURLE_OK)
681
0
            fprintf(stderr, "curl_easy_perform() failed: %s\n",
682
0
                    curl_easy_strerror(res));
683
14
684
14
        /* always cleanup */
685
14
        curl_easy_cleanup(curl);
686
14
    }
687
14
    curl_global_cleanup();
688
14
    int start = readBuffer.find("<h2 class=\"polution\">");
689
14
    try {
690
14
        readBuffer = readBuffer.substr(start, 40);
691
14
    }
692
14
    catch (...){
693
0
        log_file_mutex.mutex_lock();
694
0
        log_file_cout << CRITICAL << "wyjatek substr() e getSmog() !!!!!!"<< std::endl;
695
0
        log_file_mutex.mutex_unlock();
696
0
    }
697
14
698
14
    readBuffer = useful_F_libs::find_tag(readBuffer);
699
14
700
14
    return readBuffer;
701
14
}
702
703
void iDomTOOLS::send_temperature_thingSpeak()
704
8
{
705
8
    std::vector<std::string> _temperature = getTemperature();
706
8
    std::string addres = "api.thingspeak.com/update?key=";
707
8
    addres+=key;
708
8
    addres+="&field1=";
709
8
    addres+= _temperature.at(0);
710
8
    // addres.erase(addres.size()-2,addres.size());
711
8
    addres+= "&field3="+_temperature.at(1);
712
8
    addres+="&field2="+getSmog();
713
8
    //////////////////////////////// pozyskanie temperatury
714
8
    allThermometer.updateAll(&_temperature);
715
8
    sendSMSifTempChanged("outside",0);
716
8
    sendSMSifTempChanged("inside",24);
717
8
    std::string s = useful_F_libs::httpPost(addres,10);
718
8
719
8
    if(s == "0"){
720
0
        log_file_mutex.mutex_lock();
721
0
        log_file_cout << CRITICAL << " błąd wysyłania temoeratury na thingspeak: "<< s << std::endl;
722
0
        log_file_mutex.mutex_unlock();
723
0
    }
724
8
}
725
726
void iDomTOOLS::cameraLedON(const std::string& link)
727
3
{
728
3
    Clock t = Clock::getTime();
729
3
    SunRiseSet sun;
730
3
    Clock sunRise, sunSet;
731
3
    sunRise = sun.getSunRise();
732
3
    sunSet = sun.getSunSet();
733
3
    sunSet += Clock(23,30); // +23:30 == -00:30
734
3
    if (t <= sunRise || t >= sunSet){
735
2
        //printf("zapalam leda!\n");
736
2
        std::string s = useful_F_libs::httpPost(link,10);
737
2
        if (s == "ok.\n"){
738
2
            my_data->main_iDomStatus->setObjectState("cameraLED",STATE::ON);
739
2
            // printf("w ifie\n");
740
2
        }
741
2
    }
742
3
    // printf("nie odpalam leda!\n");
743
3
}
744
745
void iDomTOOLS::cameraLedOFF(const std::string& link)
746
3
{
747
3
    std::string s = useful_F_libs::httpPost(link,10);
748
3
    //printf (" camera response '%s' \n", s.c_str());
749
3
    if (s == "ok.\n"){
750
3
        my_data->main_iDomStatus->setObjectState("cameraLED",STATE::OFF);
751
3
        //printf("w ifie\n");
752
3
    }
753
3
}
754
755
nlohmann::json iDomTOOLS::sendViberMsg(const std::string &msg,
756
                                       const std::string &receiver,
757
                                       const std::string &senderName,
758
                                       const std::string& accessToken,
759
                                       const std::string& url)
760
11
{
761
11
    nlohmann::json jj;
762
11
    std::lock_guard<std::mutex> lock(m_msgMutex);
763
11
    jj = nlohmann::json::parse( m_viber.sendViberMSG(msg,receiver,senderName,accessToken,url));
764
11
    return jj;
765
11
}
766
767
nlohmann::json iDomTOOLS::sendViberPicture(const std::string &msg,
768
                                           const std::string &image,
769
                                           const std::string &receiver,
770
                                           const std::string &senderName,
771
                                           const std::string& accessToken,
772
                                           const std::string& url)
773
25
{
774
25
    nlohmann::json jj;
775
25
    std::lock_guard<std::mutex> lock(m_msgMutex);
776
25
    jj = nlohmann::json::parse(m_viber.sendViberPicture(msg,image,receiver,senderName,accessToken,url));
777
25
    return jj;
778
25
}
779
780
STATE iDomTOOLS::sendViberMsgBool(const std::string &msg,
781
                                  const std::string &receiver,
782
                                  const std::string &senderName,
783
                                  const std::string& accessToken,
784
                                  const std::string& url)
785
2
{
786
2
    nlohmann::json jj = sendViberMsg(msg,receiver,senderName,accessToken,url);
787
2
    STATE ret = STATE::SEND_NOK;
788
2
    if(jj.find("status_message")!= jj.end())
789
0
    {
790
0
        if(jj.at("status_message").get<std::string>() == "ok")
791
0
        {
792
0
            ret = STATE::SEND_OK;
793
0
        }
794
0
    }
795
2
    else
796
2
    {
797
2
        log_file_mutex.mutex_lock();
798
2
        log_file_cout << ERROR << "nie wyslanno wiadomosci viber"<< jj.dump()<< std::endl;
799
2
        log_file_mutex.mutex_unlock();
800
2
    }
801
2
    return ret;
802
2
}
803
804
STATE iDomTOOLS::sendViberPictureBool(const std::string& msg,
805
                                      const std::string& image,
806
                                      const std::string& receiver,
807
                                      const std::string& senderName,
808
                                      const std::string& accessToken,
809
                                      const std::string& url)
810
0
{
811
0
    nlohmann::json jj = sendViberPicture(msg,image,receiver,senderName,accessToken,url);
812
0
    STATE ret = STATE::SEND_NOK;
813
0
    if(jj.at("status_message").get<std::string>() == "ok")
814
0
    {
815
0
        ret = STATE::SEND_OK;
816
0
    }
817
0
    else
818
0
    {
819
0
        log_file_mutex.mutex_lock();
820
0
        log_file_cout << ERROR << "nie wyslanno wiadomosci viber"<< jj.dump()<< std::endl;
821
0
        log_file_mutex.mutex_unlock();
822
0
    }
823
0
    return ret;
824
0
}
825
826
std::string iDomTOOLS::postOnFacebook(const std::string& msg, const std::string& image)
827
2
{
828
2
    std::lock_guard<std::mutex> lock(m_msgMutex);
829
2
    if (image != "NULL"){
830
2
        return m_facebook.postPhotoOnWall(image,msg);
831
2
    }
832
0
833
0
    return m_facebook.postTxtOnWall(msg);
834
0
}
835
836
std::string iDomTOOLS::ledOFF()
837
12
{
838
12
    return useful_F::send_to_arduino(my_data,"LED_STOP:2;");
839
12
}
840
841
std::string iDomTOOLS::ledClear()
842
1
{
843
1
    return useful_F::send_to_arduino(my_data,"LED_CLEAR:2;");
844
1
}
845
846
std::string iDomTOOLS::ledClear(unsigned int from, unsigned int to)
847
13
{
848
13
    LED_Strip ledColor(0,60,0,0,0,"BLACK");
849
13
    useful_F::send_to_arduino(my_data,ledColor.get(from, to));
850
13
    return "Led cleared";
851
13
}
852
853
std::string iDomTOOLS::ledOn(const LED_Strip& ledColor, unsigned int from, unsigned int to)
854
21
{
855
21
    if (my_data->idom_all_state.houseState == STATE::UNLOCK)
856
3
    {
857
3
        return useful_F::send_to_arduino(my_data,ledColor.get(from, to));
858
3
    }
859
18
    else{
860
18
        my_data->myEventHandler.run("LED")->addEvent("LED can not start due to home state: "+
861
18
                                                     stateToString(my_data->idom_all_state.houseState));
862
18
    }
863
21
    return "iDom LOCKED!";
864
21
}
865
866
void iDomTOOLS::checkAlarm()
867
10
{
868
10
    unsigned int fromVol = my_data->alarmTime.fromVolume;
869
10
    unsigned int toVol   = my_data->alarmTime.toVolume;
870
10
    unsigned int radioId = my_data->alarmTime.radioID;
871
10
872
10
    Clock now = Clock::getTime();
873
10
    if (now == my_data->alarmTime.time && my_data->alarmTime.state == STATE::ACTIVE){
874
1
        my_data->alarmTime.state = STATE::WORKING;
875
1
        MPD_volumeSet(my_data, fromVol);
876
1
        MPD_play(my_data,radioId);
877
1
        my_data->main_iDomStatus->setObjectState("alarm",STATE::DEACTIVE);
878
1
    }
879
10
880
10
    if (my_data->alarmTime.state == STATE::WORKING){
881
10
        unsigned int vol = MPD_getVolume(my_data) + 1;
882
10
        if (vol < toVol){
883
9
            MPD_volumeSet(my_data, vol);
884
9
885
9
            if(iDomTOOLS::isItDay() == false){
886
9
                my_data->main_iDomTools->ledOn(my_data->ptr_pilot_led->colorLED[2],fromVol,vol);
887
9
            }
888
9
        }
889
1
        else{
890
1
            my_data->alarmTime.state = STATE::DEACTIVE;
891
1
            if(iDomTOOLS::isItDay() == false){
892
1
                // my_data->main_iDomTools->turnOn433MHzSwitch("ALARM");
893
1
            }
894
1
        }
895
10
    }
896
10
}
897
898
void iDomTOOLS::saveState_iDom()
899
47
{
900
47
    iDom_SAVE_STATE info(my_data->server_settings->saveFilePath);
901
47
    nlohmann::json jsonAlarm;
902
47
    nlohmann::json jsonMPD;
903
47
    nlohmann::json json_iDomLOCK;
904
47
    nlohmann::json json433Mhz;
905
47
    //////////////////// iDom
906
47
    json_iDomLOCK["iDomLock"] = stateToString(my_data->idom_all_state.houseState);
907
47
    //////////////////// alarm
908
47
    jsonAlarm["alarm"] = my_data->main_iDomStatus->getObjectStateString("alarm");
909
47
    jsonAlarm["time"]  = my_data->alarmTime.time.getString();
910
47
    jsonAlarm["fromVolume"] = my_data->alarmTime.fromVolume;
911
47
    jsonAlarm["toVolume"] = my_data->alarmTime.toVolume;
912
47
    jsonAlarm["radioID"] = my_data->alarmTime.radioID;
913
47
    //////////////////// mpd
914
47
    jsonMPD["music"] = my_data->main_iDomStatus->getObjectStateString("music");
915
47
    jsonMPD["speakers"] = my_data->main_iDomStatus->getObjectStateString("speakers");
916
47
    ////////////////// 433Mhz
917
47
    auto switch433vector = my_data->main_REC->getSwitchPointerVector();
918
47
    for (auto v : switch433vector)
919
235
    {
920
235
        v->getName();
921
235
        json433Mhz[v->getName()] = stateToString(v->getState());
922
235
    }
923
47
    ///
924
47
    nlohmann::json json;
925
47
    json["iDom"] = json_iDomLOCK;
926
47
    json["ALARM"] = jsonAlarm;
927
47
    json["MPD"] = jsonMPD;
928
47
    json["433Mhz"] = json433Mhz;
929
47
930
47
    info.write(json);
931
47
#ifdef BT_TEST
932
47
    std::cout << json <<std::endl;
933
47
    std::cout << " saved to " << my_data->server_settings->saveFilePath <<std::endl;
934
47
#endif
935
47
}
936
937
void iDomTOOLS::readState_iDom()
938
2
{
939
2
    try
940
2
    {
941
2
        iDom_SAVE_STATE info(my_data->server_settings->saveFilePath);
942
2
        nlohmann::json jj = info.read();
943
2
#ifdef BT_TEST
944
2
        std::cout << "JSON: " << jj.dump(4) << std::endl;
945
2
#endif
946
2
        nlohmann::json json433MHz = jj.at("433Mhz");
947
2
948
7
        for (nlohmann::json::iterator it = json433MHz.begin(); it != json433MHz.end(); ++it)
949
5
        {
950
5
            if( it.value() == "ON"){
951
0
                my_data->main_iDomTools->turnOn433MHzSwitch(it.key());
952
0
            }
953
5
            else if ( it.value() == "OFF"){
954
0
                my_data->main_iDomTools->turnOff433MHzSwitch(it.key());
955
0
            }
956
5
        }
957
2
        auto iDomLock = jj.at("iDom").at("iDomLock").get<std::string>();
958
2
959
2
        if(iDomLock == "UNLOCK")
960
0
            unlockHome();
961
2
        else if (iDomLock == "LOCK")
962
1
            lockHome();
963
2
964
2
        auto mpdMusic = jj.at("MPD").at("music").get<std::string>();
965
2
        auto mpdSpeakers = jj.at("MPD").at("speakers").get<std::string>();
966
2
967
2
        if(mpdMusic == "PLAY")
968
1
            MPD_play(my_data);
969
1
        else if(mpdMusic == "STOP")
970
0
            MPD_stop();
971
2
        if(mpdSpeakers == "ON")
972
1
            turnOnSpeakers();
973
1
        else if(mpdSpeakers == "OFF")
974
0
            turnOffSpeakers();
975
2
976
2
        auto alarmState = jj.at("ALARM").at("alarm").get<std::string>();
977
2
        auto alarmTime  = jj.at("ALARM").at("time").get<std::string>();
978
2
        my_data->alarmTime.fromVolume = jj.at("ALARM").at("fromVolume").get<int>();
979
2
        my_data->alarmTime.toVolume = jj.at("ALARM").at("toVolume").get<int>();
980
2
        my_data->alarmTime.radioID = jj.at("ALARM").at("radioID").get<int>();
981
2
        my_data->alarmTime.time = Clock(alarmTime);
982
2
983
2
        if (alarmState == "ACTIVE"){
984
1
            my_data->alarmTime.state = STATE::ACTIVE;
985
1
            my_data->main_iDomStatus->setObjectState("alarm", my_data->alarmTime.state);
986
1
            saveState_iDom();
987
1
        }
988
2
    }
989
2
    catch(...)
990
2
    {
991
1
        log_file_mutex.mutex_lock();
992
1
        log_file_cout << ERROR << "nie ma pliku json z stanem iDom"<< std::endl;
993
1
        log_file_mutex.mutex_unlock();
994
1
#ifdef BT_TEST
995
1
        std::cout << "nie ma pliku json z stanem iDom" << std::endl;
996
1
#endif
997
1
    }
998
2
}
999
1000
std::string iDomTOOLS::startKodi_Thread()
1001
4
{
1002
4
    STATE kodiState = my_data->main_iDomStatus->getObjectState("KODI");
1003
4
    if (kodiState == STATE::ACTIVE)
1004
1
        return "kodi already run";
1005
3
1006
3
    return iDOM_THREAD::start_thread("kodi smartTV",useful_F::kodi,my_data);
1007
3
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDomTools/test/lightning_BT.cpp
Line
Count
Source
1
#include <gtest/gtest.h>
2
3
#include "test_data.h"
4
#include "testJSON.h"
5
#include "../idomtools.h"
6
7
class lightning_Class : public ::testing::Test
8
{
9
protected:
10
    TEST_JSON test_Json;
11
    LIGHTNING test_lightning;
12
    CARDINAL_DIRECTIONS::ALARM_INFO test_struct;
13
    virtual void SetUp() final
14
5
    {
15
5
        std::cout << "konfiguracja przed testem lightning_Class " <<std::endl;
16
5
    }
17
18
    virtual void TearDown() final
19
5
    {
20
5
        std::cout << "czyszczenie po tescie lightning_Class " <<std::endl;
21
5
    }
22
};
23
24
TEST_F(lightning_Class, lightningAlertOFF)
25
1
{
26
1
    test_struct = test_lightning.lightningAlert(test_Json.jj_noLightning);
27
1
    std::cout <<std::endl << test_struct.data.str();
28
3
    EXPECT_FALSE(test_struct.riseAlarm) << "BRAK ALARMU";
29
1
}
30
31
TEST_F(lightning_Class, lightningAlertON)
32
1
{
33
1
    test_struct = test_lightning.lightningAlert(test_Json.jj_lightning);
34
1
    std::cout <<std::endl << test_struct.data.str();
35
3
    EXPECT_TRUE(test_struct.riseAlarm) << "BRAK ALARMU";
36
1
}
37
38
TEST_F(lightning_Class, checkLightningAlert)
39
1
{
40
1
41
1
    nlohmann::json test_Json2 = useful_F_libs::getJson("http://cyniu88.no-ip.pl/test/json/on_lightning.json");
42
1
    test_struct = test_lightning.lightningAlert(test_Json.jj_noLightning);
43
1
44
1
    bool test_result = test_lightning.checkLightningAlert(&test_struct);
45
1
46
3
    EXPECT_FALSE(test_result) << "BRAK ALARMU 1";
47
1
    test_struct = test_lightning.lightningAlert(test_Json2);
48
1
    test_result = test_lightning.checkLightningAlert(&test_struct);
49
3
    EXPECT_TRUE(test_result) << "BRAK ALARMU 2";
50
1
    test_result = test_lightning.checkLightningAlert(&test_struct);
51
3
    EXPECT_FALSE(test_result) << "BRAK ALARMU 3";
52
1
    test_struct.riseAlarm = false;
53
1
    test_result = test_lightning.checkLightningAlert(&test_struct);
54
3
    EXPECT_FALSE(test_result) << "BRAK ALARMU 4";
55
1
    test_struct.riseAlarm = false;
56
1
    test_result = test_lightning.checkLightningAlert(&test_struct);
57
3
    EXPECT_FALSE(test_result) << "BRAK ALARMU 5";
58
1
}
59
60
TEST_F(lightning_Class, checkLightningAlert_stormCloser)
61
1
{
62
1
    nlohmann::json test_Json2 = useful_F_libs::getJson("http://cyniu88.no-ip.pl/test/json/on_lightning.json");
63
1
64
1
    test_struct = test_lightning.lightningAlert(test_Json.jj_noLightning);
65
1
    bool test_result = test_lightning.checkLightningAlert(&test_struct);
66
3
    EXPECT_FALSE(test_result) << "BRAK ALARMU 1";
67
1
68
1
    test_struct = test_lightning.lightningAlert(test_Json2);
69
1
    test_result = test_lightning.checkLightningAlert(&test_struct);
70
3
    EXPECT_TRUE(test_result) << "BRAK ALARMU 2";
71
1
72
1
    test_result = test_lightning.checkLightningAlert(&test_struct);
73
3
    EXPECT_FALSE(test_result) << "BRAK ALARMU 3";
74
1
75
1
    test_struct = test_lightning.lightningAlert(test_Json.jj_lightning_lt15km);
76
1
    test_result = test_lightning.checkLightningAlert(&test_struct);
77
3
    EXPECT_TRUE(test_result) << "BRAK ALARMU 4";
78
1
79
1
    test_struct = test_lightning.lightningAlert(test_Json.jj_lightning_lt15km);
80
1
    test_result = test_lightning.checkLightningAlert(&test_struct);
81
3
    EXPECT_FALSE(test_result) << "BRAK ALARMU 5";
82
1
83
1
    test_struct = test_lightning.lightningAlert(test_Json.jj_noLightning);
84
1
    test_result = test_lightning.checkLightningAlert(&test_struct);
85
3
    EXPECT_FALSE(test_result) << "BRAK ALARMU 6";
86
1
87
1
    test_struct = test_lightning.lightningAlert(test_Json.jj_lightning_lt15km);
88
1
    test_result = test_lightning.checkLightningAlert(&test_struct);
89
3
    EXPECT_TRUE(test_result) << "BRAK ALARMU 7";
90
1
}
91
92
TEST_F(lightning_Class, oneLightning)
93
1
{
94
1
    test_struct = test_lightning.lightningAlert(test_Json.jj_oneLightning);
95
1
    bool test_result = test_lightning.checkLightningAlert(&test_struct);
96
    EXPECT_FALSE(test_result);
97
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDomTools/idomtools_mpd.cpp
Line
Count
Source
1
#include "idomtools.h"
2
#include "../blockQueue/blockqueue.h"
3
#include "../functions/functions.h"
4
5
void iDomTOOLS::MPD_play(thread_data* my_data)
6
11
{
7
11
    if(my_data->idom_all_state.houseState == STATE::UNLOCK)
8
6
    {
9
6
        blockQueue _q;
10
6
        _q._add(MPD_COMMAND::PLAY);
11
6
    }
12
5
    else
13
5
    {
14
5
        my_data->myEventHandler.run("MPD")->addEvent("MPD can not start due to home state: "+
15
5
                                                     stateToString(my_data->idom_all_state.houseState));
16
5
    }
17
11
}
18
19
void iDomTOOLS::MPD_stop()
20
13
{
21
13
    blockQueue _q;
22
13
    _q._add(MPD_COMMAND::STOP);
23
13
}
24
25
void iDomTOOLS::MPD_next()
26
2
{
27
2
    blockQueue _q;
28
2
    _q._add(MPD_COMMAND::NEXT);
29
2
}
30
31
void iDomTOOLS::MPD_prev()
32
2
{
33
2
    blockQueue _q;
34
2
    _q._add(MPD_COMMAND::PREV);
35
2
}
36
37
void iDomTOOLS::MPD_pause()
38
5
{
39
5
    blockQueue _q;
40
5
    _q._add(MPD_COMMAND::PAUSE);
41
5
}
42
43
void iDomTOOLS::MPD_volumeUp()
44
2
{
45
2
    blockQueue _q;
46
2
    _q._add(MPD_COMMAND::VOLUP);
47
2
}
48
49
void iDomTOOLS::MPD_volumeDown()
50
2
{
51
2
    blockQueue _q;
52
2
    _q._add(MPD_COMMAND::VOLDOWN);
53
2
}
54
55
void iDomTOOLS::MPD_volumeSet(thread_data *my_data, int vol)
56
12
{
57
12
    my_data->ptr_MPD_info->volume = vol;
58
12
    blockQueue _q;
59
12
    _q._add(MPD_COMMAND::VOLSET);
60
12
}
61
62
void iDomTOOLS::MPD_play(thread_data *my_data, int id)
63
4
{
64
4
    if(my_data->idom_all_state.houseState == STATE::UNLOCK)
65
2
    {
66
2
        my_data->ptr_MPD_info->currentSongID = id;
67
2
        blockQueue _q;
68
2
        _q._add(MPD_COMMAND::PLAY_ID);
69
2
    }
70
2
    else
71
2
    {
72
2
        my_data->myEventHandler.run("MPD")->addEvent("MPD can not start due to home state: "+
73
2
                                                     stateToString(my_data->idom_all_state.houseState));
74
2
    }
75
4
}
76
77
int iDomTOOLS::MPD_getVolume(thread_data *my_data)
78
11
{
79
11
    return my_data->ptr_MPD_info->volume;
80
11
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/logger/logger.cc
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * logger.cc
3
 *
4
 *
5
 * Logger Library
6
 *
7
 *
8
 * Copyright (C) 2013-2014  Bryant Moscon - bmoscon@gmail.com
9
 * 
10
 * Permission is hereby granted, free of charge, to any person obtaining a copy
11
 * of this software and associated documentation files (the "Software"), to 
12
 * deal in the Software without restriction, including without limitation the 
13
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
14
 * sell copies of the Software, and to permit persons to whom the Software is
15
 * furnished to do so, subject to the following conditions:
16
 *
17
 * 1. Redistributions of source code must retain the above copyright notice, 
18
 *    this list of conditions, and the following disclaimer.
19
 *
20
 * 2. Redistributions in binary form must reproduce the above copyright notice, 
21
 *    this list of conditions and the following disclaimer in the documentation 
22
 *    and/or other materials provided with the distribution, and in the same 
23
 *    place and form as other copyright, license and disclaimer information.
24
 *
25
 * 3. The end-user documentation included with the redistribution, if any, must 
26
 *    include the following acknowledgment: "This product includes software 
27
 *    developed by Bryant Moscon (http://www.bryantmoscon.org/)", in the same 
28
 *    place and form as other third-party acknowledgments. Alternately, this 
29
 *    acknowledgment may appear in the software itself, in the same form and 
30
 *    location as other such third-party acknowledgments.
31
 *
32
 * 4. Except as contained in this notice, the name of the author, Bryant Moscon,
33
 *    shall not be used in advertising or otherwise to promote the sale, use or 
34
 *    other dealings in this Software without prior written authorization from 
35
 *    the author.
36
 *
37
 *
38
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
39
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
40
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
41
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
42
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
44
 * THE SOFTWARE.
45
 *
46
 */
47
48
#include "logger.hpp"
49
50
pthread_mutex_t Logger::mutex_log = PTHREAD_MUTEX_INITIALIZER;
51
52
Logger::Logger(const char *f) : _file(f, std::ios::out | std::ios::app), 
53
        _log(_file),
54
        _level(INFO),
55
        _line_level(VERBOSE)
56
0
{
57
0
  assert(_file.is_open());
58
0
}
59
60
61
Logger::Logger(const std::string& f) : _file(f.c_str(), std::ios::out | std::ios::app), 
62
               _log(_file),
63
               _level(INFO),
64
               _line_level(VERBOSE)
65
0
{
66
0
  assert(_file.is_open());
67
0
}
68
69
70
Logger::~Logger()
71
0
{
72
0
  if (_file.is_open()) {
73
0
    _log.flush();
74
0
    _file.close();
75
0
  }
76
0
}
77
78
void Logger::set_level(const logger_level& level)
79
0
{
80
0
  _level = level;
81
0
}  
82
 
83
84
void Logger::flush()
85
92
{
86
92
  if (_line_level >= _level) {
87
80
    _log << get_time() << " -- [" << level_str(_line_level) << "] -- " << str();
88
80
    _log.flush();
89
80
  }
90
92
  else
91
92
  {
92
12
      _log << get_time() << " -- [" << level_str(_line_level) << "] -- " << str();
93
12
      _log.flush();
94
12
  }
95
92
96
92
  str("");
97
92
  _line_level = VERBOSE;
98
92
}
99
100
101
Logger& Logger::operator<<(const logger_level& level)
102
87
{
103
87
  _line_level = level;
104
87
  return (*this);
105
87
}
106
107
108
Logger& Logger::operator<<(LoggerManip m)
109
92
{ 
110
92
  return m(*this);
111
92
}
112
113
114
std::string Logger::get_time() const
115
92
{
116
92
  struct tm *timeinfo;
117
92
  time_t rawtime;
118
92
  char *time_buf;
119
92
  
120
92
  time(&rawtime);
121
92
  timeinfo = localtime(&rawtime);
122
92
  time_buf = asctime(timeinfo);
123
92
  
124
92
  std::string ret(time_buf);
125
92
  if (!ret.empty() && ret[ret.length() - 1] == '\n') {
126
92
    ret.erase(ret.length()-1);
127
92
  }
128
92
  
129
92
  return (ret);
130
92
}
131
132
133
inline const char* Logger::level_str(const logger_level& level)
134
92
{
135
92
  switch (level) {
136
7
  case VERBOSE:
137
7
    return ("VERBOSE ");
138
7
  case DEBUG:
139
5
    return (" DEBUG  ");
140
53
  case INFO:
141
53
    return ("  INFO  ");
142
7
  case WARNING:
143
6
    return ("WARNING ");
144
9
  case ERROR:
145
9
    return (" ERROR  ");
146
11
  case CRITICAL:
147
11
    return ("CRITICAL");
148
7
  case FATAL:
149
1
    return (" FATAL  ");
150
7
  default:
151
0
    assert(false);
152
0
  } 
153
92
}
154
void Logger::mutex_lock()
155
87
{
156
87
    pthread_mutex_lock(&Logger::mutex_log);
157
87
}
158
159
void Logger::mutex_unlock()
160
87
{
161
87
    pthread_mutex_unlock(&Logger::mutex_log);
162
87
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDomTools/idomtools_system.cpp
Line
Count
Source
1
#include "idomtools.h"
2
#include <sys/sysinfo.h>
3
#include <sys/utsname.h>
4
#include <sys/resource.h>
5
#include <sys/time.h>
6
#include <unistd.h>
7
8
std::string iDomTOOLS::getSystemInfo()
9
2
{
10
2
    double load[3];
11
2
    if (getloadavg(load, 3) != -1)
12
2
    {
13
2
#ifdef BT_TEST
14
2
        printf("load average : %f , %f , %f\n", load[0],load[1],load[2]);
15
2
#endif
16
2
    }
17
2
    const double megabyte = 1024 * 1024;
18
2
    struct sysinfo info;
19
2
    sysinfo(&info);
20
2
21
2
    long input_seconds = info.uptime;
22
2
    auto days = input_seconds / 60 / 60 / 24;
23
2
    auto hours = (input_seconds / 60 / 60) % 24;
24
2
    auto minutes = (input_seconds / 60) % 60;
25
2
    auto seconds = input_seconds % 60;
26
2
27
2
    std::stringstream ret;
28
2
    ret << "System uptime: " << days <<" day " << hours
29
2
        << " hours " << minutes << " minutes "
30
2
        << seconds << " seconds " << std::endl << "Load: "
31
2
        << (info.loads[0]/65536) << "% - 1 min, " <<(info.loads[1]/65536)
32
2
        << "% - 5 min, "<<(info.loads[2]/65536) << "% - 15 min." << std::endl
33
2
        << "process count : " << info.procs << std::endl
34
2
        << "total RAM   : "<< (info.totalram / megabyte)<< "MB" << std::endl
35
2
        << "free RAM   : " << (info.freeram / megabyte) << "MB" << std::endl;
36
2
37
2
    return ret.str();
38
2
}
39
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/menu_tree/menu_tree.cpp
Line
Count
Source (jump to first uncovered line)
1
#include "menu_tree.h"
2
3
menu_tree::menu_tree (const std::string &path, LCD_c *mainLCD_PTR):database_path(path),w_serial( "([Ss]\\d{1,3}[Ee]\\d{1,3})")
4
12
{
5
12
    mainLCD=mainLCD_PTR;
6
12
7
12
    i_stack.push(0);
8
12
    i=0;
9
12
    get_list(database_path);
10
12
}
11
12
bool menu_tree::is_file() const
13
7
{
14
7
    return movie_database_vector[i].is_file;
15
7
}
16
//std::string menu_tree::return_path( int i) const
17
//{
18
19
//    return movie_database_vector[i].path;
20
//}
21
22
//void menu_tree::get_main_list()
23
//{
24
//    get_list( database_path );
25
//}
26
void menu_tree::next()
27
23
{   
28
23
    ++i;
29
23
    if (get_vector_size() == i ){
30
2
        i=0;
31
2
    }
32
23
}
33
34
void menu_tree::previous()
35
6
{
36
6
    --i;
37
6
    if ( i <0 )
38
6
    {
39
1
        i=get_vector_size()-1;
40
1
    }
41
6
}
42
43
int menu_tree::get_vector_size () const
44
24
{
45
24
    return movie_database_vector.size();
46
24
}
47
void menu_tree::vector_clear ()
48
14
{
49
14
    movie_database_vector.clear();
50
14
}
51
int menu_tree::get_i()
52
1
{
53
1
    if (i_stack.size() >1 ) {
54
1
        int i = i_stack.top();
55
1
        i_stack.pop();
56
1
        return i;
57
1
    }
58
1
    else
59
1
        return 0;
60
1
}
61
62
void menu_tree::enter_dir()
63
1
{
64
1
    i_stack.push(i); // wpisuje na stos kolejna wersje licznika i
65
1
    
66
1
    if (movie_database_vector[i].is_file == true ) {
67
0
68
0
    }
69
1
    else {
70
1
        get_list (movie_database_vector[i].path);
71
1
        i=0;
72
1
    }
73
1
}
74
//void menu_tree::enter_dir(const std::string& path)
75
//{
76
//    get_list (path) ;
77
//}
78
79
void menu_tree::back_dir()
80
1
{
81
1
    if ( tree_stack.size() >1 ) {
82
1
        tree_stack.pop();
83
1
        std::string path = tree_stack.top();
84
1
        tree_stack.pop();
85
1
        i = get_i();
86
1
        get_list (path);
87
1
        return;
88
1
    }
89
1
    i = get_i();
90
0
    get_list (database_path);
91
0
    return;
92
1
}
93
94
std::string menu_tree::show_list()
95
60
{
96
60
    if (movie_database_vector[i].is_file == true ) {
97
40
        mainLCD->printString(true,0,0,movie_database_vector[i].files_name.substr(0,16));
98
40
99
40
        return movie_database_vector[i].files_name;
100
40
    }
101
60
    else {
102
20
        mainLCD->printString(true,0,0,movie_database_vector[i].files_name+" ->");
103
20
    }
104
60
105
60
    return movie_database_vector[i].path;
106
60
}
107
bool comper (const movie_database & a , const movie_database& b);
108
//{
109
//    return a.files_name < b.files_name;
110
//}
111
112
14
void menu_tree::get_list(const std::string& path) {
113
14
    tree_stack.push(path);
114
14
    vector_clear(); // czyscimy vector
115
14
    std::string path2(path);
116
14
    std::string v_path ,tmp_string;
117
14
    if(sciezka = opendir( path.c_str() )) {
118
13
119
13
120
104
        while(( plik = readdir( sciezka ) ) )
121
91
        {
122
91
            path2 =path;
123
91
            if (static_cast<int>(plik->d_type) == 4 /*&& strcmp( plik->d_name, "..") && strcmp( plik->d_name, ".")*/ )
124
91
            {
125
52
                if (!strcmp( plik->d_name, "..") || !strcmp( plik->d_name, "."))
126
52
                {continue;}
127
52
                temp.is_file=false;
128
26
            }
129
91
            else //if ( (int)plik->d_type == 8 && strcmp( plik->d_name, "..") && strcmp( plik->d_name, "."))
130
91
            {
131
39
                temp.is_file=true;
132
39
            }
133
91
134
91
            v_path= path2;
135
65
            v_path+="/";
136
65
            tmp_string.assign(plik->d_name);
137
65
            v_path+=tmp_string;
138
65
            temp.path =v_path;
139
65
            temp.files_name.assign(plik->d_name);
140
65
            movie_database_vector.push_back(temp);
141
65
142
65
        } // end while
143
13
        sort(movie_database_vector.begin(),movie_database_vector.end(), comper);
144
13
        closedir( sciezka );
145
13
    }
146
14
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDomTools/lightning.cpp
Line
Count
Source
1
#include "lightning.h"
2
3
LIGHTNING::LIGHTNING()
4
392
{
5
392
    puts("LIGHTNING::LIGHTNING()");
6
392
}
7
8
LIGHTNING::~LIGHTNING()
9
392
{
10
392
    puts("LIGHTNING::~LIGHTNING()");
11
392
}
12
13
CARDINAL_DIRECTIONS::ALARM_INFO LIGHTNING::lightningAlert(nlohmann::json jj)
14
13
{
15
13
    CARDINAL_DIRECTIONS::ALARM_INFO data;
16
13
    nlohmann::json i;
17
13
18
13
#ifdef BT_TEST
19
13
    std::cout <<"\n\n data all " << i.dump(4) <<" size:"<< i.size() <<std::endl;
20
13
#endif
21
13
    if (jj.find("response") != jj.end())
22
12
    {
23
12
        i = jj.at("response").get<nlohmann::json>();
24
12
    }
25
1
    else
26
1
    {
27
1
        std::cout << " zly JSON " <<std::endl;
28
1
        return data;
29
1
    }
30
12
31
12
    auto _size = i.size();
32
12
    if (_size == 0)
33
4
    {
34
4
        data.riseAlarm = false;
35
4
        return data;
36
4
    }
37
8
    STATISTIC<int> ageAver(_size);
38
8
    STATISTIC<double> distanceKmAver(_size);
39
8
    STATISTIC<int> bearingAver(_size);
40
146
    for (auto j : i){
41
146
#ifdef BT_TEST
42
146
   //     std::cout <<"\n distance " << j.at("relativeTo").at("bearingENG").get<std::string>() << std::endl;
43
146
   //     std::cout <<"distance " << j.at("relativeTo").at("distanceKM").get<double>() << std::endl;
44
146
   //     std::cout <<"timestamp " << j.at("age").get<int>() << std::endl;
45
146
#endif
46
146
        ageAver.push_back(j.at("age").get<int>());
47
146
        distanceKmAver.push_back(j.at("relativeTo").at("distanceKM").get<double>());
48
146
        bearingAver.push_back(static_cast<int>(CARDINAL_DIRECTIONS::stringToCardinalDirectionsEnum(
49
146
                                                   j.at("relativeTo").at("bearingENG").get<std::string>()))
50
146
                              );
51
146
    }
52
8
    data.bearingENG = static_cast<CARDINAL_DIRECTIONS::CARDINAL_DIRECTIONS_ENUM>(bearingAver.mode());
53
8
    data.distance = distanceKmAver.average();
54
8
    data.timestamp = ageAver.median();
55
8
56
8
    data.data.str(std::string());
57
8
    data.data << "ilość uderzeń: "<< _size << "\\n";
58
8
    data.data << "średni czas upłynięty od ostatniego uderzenia pioruna: "<< data.timestamp << " sek \\n";
59
8
    data.data << "średnia odległość ostatniego uderzenia pieruna: "<< data.distance <<" km \\n ";
60
8
    data.data << "kierunek uderzeń piorunów: " << CARDINAL_DIRECTIONS::cardinalDirectionsEnumToHuman(data.bearingENG);
61
8
62
8
    if(i.size() > 0){
63
8
        // std::cout << "jest size: " << i.size()<<std::endl;
64
8
        data.riseAlarm = true;
65
8
    }
66
8
67
8
    return data;
68
8
}
69
70
bool LIGHTNING::checkLightningAlert(CARDINAL_DIRECTIONS::ALARM_INFO *info)
71
15
{
72
15
#ifdef BT_TEST
73
15
    std::cout << "LIGHTNING::checkLightningAlert() bool "<< info->riseAlarm <<" local " << alarmState << std::endl
74
15
              << " distance " << info->distance << std::endl;
75
15
#endif
76
15
    if(info->riseAlarm == false && alarmState == false){
77
4
#ifdef BT_TEST
78
4
        std::cout << "(info->riseAlarm == false || alarmState == false)"<<std::endl;
79
4
#endif
80
4
        return false;
81
4
    }
82
11
    if(info->riseAlarm == false && alarmState == true){
83
2
#ifdef BT_TEST
84
2
        std::cout << "(info->riseAlarm == false || alarmState == true)"<<std::endl;
85
2
#endif
86
2
        alarmState = false;
87
2
        return false;
88
2
    }
89
9
    if(info->riseAlarm == true && alarmState == false){
90
5
91
5
#ifdef BT_TEST
92
5
        std::cout << "(info->riseAlarm == true || alarmState == false)"<<std::endl;
93
5
#endif
94
5
        alarmState = true;
95
5
        lightningTime = Clock::getTime();
96
5
        oldDistance = info->distance;
97
5
        std::cout << " w true oldDistance: "<< oldDistance <<std::endl;
98
5
        return true;
99
5
    }
100
4
101
4
#ifdef BT_TEST
102
4
    std::cout << "checkLightningAlert() - dystans"<<std::endl;
103
4
    std::cout << "Dystans: " <<info->distance << " oldDistance: "<< oldDistance <<std::endl;
104
4
#endif
105
4
    if(oldDistance > info->distance)
106
1
    {
107
1
108
1
        oldDistance = info->distance;
109
1
        return true;
110
1
    }
111
3
    else
112
3
    {
113
3
        oldDistance = info->distance;
114
3
    }
115
4
    ////////////////clear
116
4
    //oldDistance = 0.0;
117
4
    return false;
118
4
}
119
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/logger/logger.hpp
Line
Count
Source
1
/*
2
 * logger.hpp
3
 *
4
 *
5
 * Logger Library Header
6
 *
7
 *
8
 * Copyright (C) 2013-2014  Bryant Moscon - bmoscon@gmail.com
9
 *
10
 * Permission is hereby granted, free of charge, to any person obtaining a copy
11
 * of this software and associated documentation files (the "Software"), to
12
 * deal in the Software without restriction, including without limitation the
13
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
14
 * sell copies of the Software, and to permit persons to whom the Software is
15
 * furnished to do so, subject to the following conditions:
16
 *
17
 * 1. Redistributions of source code must retain the above copyright notice,
18
 *    this list of conditions, and the following disclaimer.
19
 *
20
 * 2. Redistributions in binary form must reproduce the above copyright notice,
21
 *    this list of conditions and the following disclaimer in the documentation
22
 *    and/or other materials provided with the distribution, and in the same
23
 *    place and form as other copyright, license and disclaimer information.
24
 *
25
 * 3. The end-user documentation included with the redistribution, if any, must
26
 *    include the following acknowledgment: "This product includes software
27
 *    developed by Bryant Moscon (http://www.bryantmoscon.org/)", in the same
28
 *    place and form as other third-party acknowledgments. Alternately, this
29
 *    acknowledgment may appear in the software itself, in the same form and
30
 *    location as other such third-party acknowledgments.
31
 *
32
 * 4. Except as contained in this notice, the name of the author, Bryant Moscon,
33
 *    shall not be used in advertising or otherwise to promote the sale, use or
34
 *    other dealings in this Software without prior written authorization from
35
 *    the author.
36
 *
37
 *
38
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
41
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
42
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
44
 * THE SOFTWARE.
45
 *
46
 */
47
#ifndef __LOGGER__
48
#define __LOGGER__
49
50
#include <fstream>
51
#include <cassert>
52
#include <ctime>
53
#include <sstream>
54
55
// Log levels
56
typedef enum {
57
    US =0,
58
    VERBOSE,
59
    DEBUG,
60
    INFO,
61
    WARNING,
62
    ERROR,
63
    CRITICAL,
64
    FATAL
65
} logger_level;
66
67
class Logger : public std::ostringstream {
68
public:
69
70
    explicit Logger(const char *f);
71
    explicit Logger(const std::string& f);
72
    Logger (const Logger &);
73
    Logger &operator= (const Logger &);
74
    ~Logger();
75
    static pthread_mutex_t mutex_log;
76
77
    void set_level(const logger_level& level);
78
    void flush();
79
    void mutex_lock();
80
    void mutex_unlock();
81
82
    template <typename T>
83
    Logger& operator<<(const T& t)
84
17
    {
85
17
        *static_cast<std::ostringstream *>(this) << t;
86
17
        return (*this);
87
17
    }
_ZN6LoggerlsIA7_cEERS_RKT_
Line
Count
Source
84
4
    {
85
4
        *static_cast<std::ostringstream *>(this) << t;
86
4
        return (*this);
87
4
    }
_ZN6LoggerlsINSt6thread2idEEERS_RKT_
Line
Count
Source
84
4
    {
85
4
        *static_cast<std::ostringstream *>(this) << t;
86
4
        return (*this);
87
4
    }
_ZN6LoggerlsIA26_cEERS_RKT_
Line
Count
Source
84
3
    {
85
3
        *static_cast<std::ostringstream *>(this) << t;
86
3
        return (*this);
87
3
    }
_ZN6LoggerlsIA3_cEERS_RKT_
Line
Count
Source
84
1
    {
85
1
        *static_cast<std::ostringstream *>(this) << t;
86
1
        return (*this);
87
1
    }
Unexecuted instantiation: _ZN6LoggerlsIPKcEERS_RKT_
_ZN6LoggerlsIA15_cEERS_RKT_
Line
Count
Source
84
5
    {
85
5
        *static_cast<std::ostringstream *>(this) << t;
86
5
        return (*this);
87
5
    }
88
89
    Logger& operator<<(const logger_level& level);
90
    typedef Logger& (* LoggerManip)(Logger&);
91
    Logger& operator<<(LoggerManip m);
92
93
private:
94
    std::string get_time() const;
95
    inline const char* level_str(const logger_level& level);
96
public:
97
    std::ofstream _file;
98
private:
99
    std::ostream& _log;
100
    logger_level _level;
101
    logger_level _line_level;
102
};
103
104
105
namespace std { 
106
inline Logger& endl(Logger& out)
107
{
108
    out.put('\n');
109
    out.flush();
110
    return (out);
111
}
112
}// end namespace std
113
114
#endif
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDomTools/lightning.h
Line
Count
Source (jump to first uncovered line)
1
#ifndef LIGHTNING_H
2
#define LIGHTNING_H
3
#include <iostream>
4
5
#include "../../libs/Statistic/statistic.h"
6
#include "../../libs/useful/useful.h"
7
8
#include "idomtools_useful.h"
9
#include "json.hpp"
10
11
class CARDINAL_DIRECTIONS{
12
public:
13
    enum class CARDINAL_DIRECTIONS_ENUM{
14
        /*
15
           N
16
        NNW NNE
17
      NW       NE
18
   WNW         ENE
19
 W            E
20
   WSW       ESE
21
      SW     SE
22
        SSW  SSE
23
           S
24
    */
25
26
        N = 1,NNE,NE,ENE,E,ESE,SE,SSE,S,SSW,SW,WSW,W,WNW,NW,NNW,ERROR
27
    };
28
148
    static CARDINAL_DIRECTIONS_ENUM stringToCardinalDirectionsEnum(std::string s){
29
148
        if (s == "N")      return CARDINAL_DIRECTIONS_ENUM::N;
30
147
        else if (s == "NNE")    return CARDINAL_DIRECTIONS_ENUM::NNE;
31
135
        else if (s == "NE")     return CARDINAL_DIRECTIONS_ENUM::NE;
32
129
        else if (s == "ENE")    return CARDINAL_DIRECTIONS_ENUM::ENE;
33
51
        else if (s == "E")      return CARDINAL_DIRECTIONS_ENUM::E;
34
3
        else if (s == "ESE")    return CARDINAL_DIRECTIONS_ENUM::ESE;
35
3
        else if (s == "SE")     return CARDINAL_DIRECTIONS_ENUM::SE;
36
3
        else if (s == "SSE")    return CARDINAL_DIRECTIONS_ENUM::SSE;
37
3
        else if (s == "S")      return CARDINAL_DIRECTIONS_ENUM::S;
38
3
        else if (s == "SSW")    return CARDINAL_DIRECTIONS_ENUM::SSW;
39
3
        else if (s == "SW")     return CARDINAL_DIRECTIONS_ENUM::SW;
40
3
        else if (s == "WSW")    return CARDINAL_DIRECTIONS_ENUM::WSW;
41
1
        else if (s == "W")      return CARDINAL_DIRECTIONS_ENUM::W;
42
1
        else if (s == "WNW")    return CARDINAL_DIRECTIONS_ENUM::WNW;
43
1
        else if (s == "NW")     return CARDINAL_DIRECTIONS_ENUM::NW;
44
1
        else if (s == "NNW")    return CARDINAL_DIRECTIONS_ENUM::NNW;
45
1
        else                    return CARDINAL_DIRECTIONS_ENUM::ERROR;
46
0
    }
47
48
2
    static std::string cardinalDirectionsEnumToString(CARDINAL_DIRECTIONS_ENUM e){
49
2
        switch (e){
50
2
        case CARDINAL_DIRECTIONS_ENUM::N:
51
0
            return "N";
52
2
        case CARDINAL_DIRECTIONS_ENUM::NNE:
53
0
            return "NNE";
54
2
        case CARDINAL_DIRECTIONS_ENUM:: NE:
55
0
            return "NE";
56
2
        case CARDINAL_DIRECTIONS_ENUM::ENE:
57
0
            return "ENE";
58
2
        case CARDINAL_DIRECTIONS_ENUM::E:
59
0
            return "E";
60
2
        case CARDINAL_DIRECTIONS_ENUM::ESE:
61
1
            return "ESE";
62
2
        case CARDINAL_DIRECTIONS_ENUM::SE:
63
0
            return "SE";
64
2
        case CARDINAL_DIRECTIONS_ENUM::SSE:
65
0
            return "SSE";
66
2
        case CARDINAL_DIRECTIONS_ENUM::S:
67
0
            return "S";
68
2
        case CARDINAL_DIRECTIONS_ENUM::SSW:
69
0
            return "SSW";
70
2
        case CARDINAL_DIRECTIONS_ENUM::SW:
71
0
            return "SW";
72
2
        case CARDINAL_DIRECTIONS_ENUM::WSW:
73
0
            return "WSW";
74
2
        case CARDINAL_DIRECTIONS_ENUM::W:
75
0
            return "W";
76
2
        case CARDINAL_DIRECTIONS_ENUM::WNW:
77
0
            return "WNW";
78
2
        case CARDINAL_DIRECTIONS_ENUM::NW:
79
0
            return "NW";
80
2
        case CARDINAL_DIRECTIONS_ENUM::NNW:
81
0
            return "NNW";
82
2
        default:
83
1
            return "UNKNOWN DIRECTION";
84
0
        }
85
0
    }
86
8
    static std::string cardinalDirectionsEnumToHuman(CARDINAL_DIRECTIONS_ENUM e){
87
8
        switch (e){
88
8
        case CARDINAL_DIRECTIONS_ENUM::N:
89
0
            return "północ";
90
8
        case CARDINAL_DIRECTIONS_ENUM::NNE:
91
0
            return "północ - północny wschód";
92
8
        case CARDINAL_DIRECTIONS_ENUM:: NE:
93
0
            return "północny wschód";
94
8
        case CARDINAL_DIRECTIONS_ENUM::ENE:
95
6
            return "wschód - północny wschód";
96
8
        case CARDINAL_DIRECTIONS_ENUM::E:
97
0
            return "wschód";
98
8
        case CARDINAL_DIRECTIONS_ENUM::ESE:
99
0
            return "wschód - południowy wschód";
100
8
        case CARDINAL_DIRECTIONS_ENUM::SE:
101
0
            return "południowy wschód";
102
8
        case CARDINAL_DIRECTIONS_ENUM::SSE:
103
0
            return "południe - południowy wschód";
104
8
        case CARDINAL_DIRECTIONS_ENUM::S:
105
0
            return "południe";
106
8
        case CARDINAL_DIRECTIONS_ENUM::SSW:
107
0
            return "południe - południowy zachów";
108
8
        case CARDINAL_DIRECTIONS_ENUM::SW:
109
0
            return "południowy zachów";
110
8
        case CARDINAL_DIRECTIONS_ENUM::WSW:
111
2
            return "zachód - południowy zachów";
112
8
        case CARDINAL_DIRECTIONS_ENUM::W:
113
0
            return "zachód";
114
8
        case CARDINAL_DIRECTIONS_ENUM::WNW:
115
0
            return "zachód - północny zachód";
116
8
        case CARDINAL_DIRECTIONS_ENUM::NW:
117
0
            return "północny zachód";
118
8
        case CARDINAL_DIRECTIONS_ENUM::NNW:
119
0
            return "północ - północny zachód";
120
8
        default:
121
0
            return "UNKNOWN DIRECTION";
122
0
        }
123
0
    }
124
    struct ALARM_INFO{
125
        ALARM_INFO():
126
            riseAlarm(false),
127
            timestamp(0),
128
            distance(0.0),
129
            bearingENG(CARDINAL_DIRECTIONS::CARDINAL_DIRECTIONS_ENUM::ERROR)
130
404
        {
131
404
            data << "NULL";
132
404
        }
133
        ALARM_INFO(const ALARM_INFO &s):
134
            riseAlarm(s.riseAlarm),
135
            data(s.data.str()),
136
            timestamp(s.timestamp),
137
            distance(s.distance),
138
            bearingENG(s.bearingENG)
139
4
        {
140
4
        }
141
        ALARM_INFO& operator = (const ALARM_INFO& s)
142
14
        {
143
14
            this->data.str(std::string());
144
14
            this->riseAlarm = s.riseAlarm;
145
14
            this->data << s.data.str();
146
14
            this->timestamp = s.timestamp;
147
14
            this->distance = s.distance;
148
14
            this->bearingENG = s.bearingENG;
149
14
            return *this;
150
14
        }
151
152
        bool riseAlarm;
153
        std::stringstream data;
154
        unsigned int timestamp; //second
155
        double distance; //km
156
        CARDINAL_DIRECTIONS::CARDINAL_DIRECTIONS_ENUM bearingENG;
157
    };
158
};
159
160
class LIGHTNING
161
{
162
public:
163
    LIGHTNING();
164
    ~LIGHTNING();
165
    CARDINAL_DIRECTIONS::ALARM_INFO lightningAlert(nlohmann::json jj);
166
    bool checkLightningAlert(CARDINAL_DIRECTIONS::ALARM_INFO* info);
167
private:
168
    bool alarmState = false;
169
    Clock lightningTime;
170
    double oldDistance = 0.0;
171
};
172
173
#endif // LIGHTNING_H
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDom_server_OOP.h
Line
Count
Source
1
#ifndef GLOBAL_H
2
#define GLOBAL_H
3
4
#include <iostream>
5
#include <fstream>
6
#include <string>
7
#include <cstdlib>
8
#include <pthread.h>
9
#include <stdio.h>
10
#include <stdlib.h>
11
#include <sys/socket.h>
12
#include <sys/types.h>
13
#include <netinet/in.h>
14
#include <vector>
15
#include <thread>
16
#include <arpa/inet.h>
17
#include <netinet/in.h>
18
#include <unistd.h>
19
#include <sys/fcntl.h>
20
#include <unistd.h>
21
#include <errno.h>
22
#include <signal.h>
23
#include <time.h>
24
#include <wiringPi.h>
25
#include <chrono>
26
#include <array>
27
28
// MOJE BIBLIOTEKI
29
#include "KEY/key.h"
30
#include "logger/logger.hpp"
31
#include "files_tree/files_tree.h"
32
#include "menu_tree/menu_tree.h"
33
#include "LCD_c/lcd_c.h"
34
#include "command/command.h"
35
#include "../libs/event_counters/event_counters_handler.h"
36
#include "iDomTools/idomtools.h"
37
#include "iDomStatus/idomstatus.h"
38
#include "iDomSaveState/idom_save_state.h"
39
40
53
#define log_file_cout  f_log //std::cout zmien f_log na std::cout i bedzie wypisywac na ekran
41
18
#define log_file_mutex f_log
42
43
enum class iDomStateEnum{
44
    CLOSE = 0,
45
    RELOAD,
46
    ERROR,
47
    WORKING,
48
    HARD_RELOAD
49
};
50
51
namespace iDomConst
52
{
53
constexpr int MAX_CONNECTION = 10;
54
constexpr int FREE  = 1;
55
constexpr int RS232 = 11;
56
constexpr int CLOCK = 12;
57
constexpr int ok    = 0;
58
constexpr int GPIO_SPIK = 21;
59
constexpr int GPIO_PRINTER = 22;
60
constexpr int BUTTON_PIN = 25;
61
}
62
struct ALERT
63
{
64
    Clock time;
65
    STATE state = STATE::DEACTIVE;
66
    unsigned int fromVolume = 48;
67
    unsigned int toVolume = 58;
68
    unsigned int radioID = 8;
69
};
70
71
extern std::string _logfile;
72
extern Logger log_file_mutex;
73
extern std::string buffer;
74
75
enum class TEMPERATURE_STATE;
76
enum class PILOT_KEY;
77
78
struct MPD_info{
79
    std::string title   = "NULL";
80
    std::string radio   = "NULL";
81
    std::string artist  = "NULL";
82
    int volume = 0;
83
    bool isPlay = false;
84
    int currentSongID = 0;
85
    std::vector <std::string> songList = {"NULL"};
86
};
87
struct s_pointer{
88
    unsigned int *ptr_who;
89
    int32_t *ptr_buf;
90
};
91
92
struct Thread_array_struc {
93
    std::thread thread;
94
    std::thread::id thread_ID = std::thread::id(0);
95
    std::string thread_name;
96
    int thread_socket = 0;
97
};
98
99
struct address_another_servers {
100
    int id;
101
    std::string SERVER_IP;
102
};
103
104
struct FTP_SERVER{
105
    std::string URL;
106
    std::string user;
107
    std::string pass;
108
};
109
struct iDOM_STATE{
110
    STATE houseState = STATE::UNDEFINE;
111
112
};
113
114
struct config{
115
    std::string portRS232;
116
    std::string portRS232_clock;
117
    std::string BaudRate;
118
    std::string RFLinkPort;
119
    std::string RFLinkBaudRate;
120
    int PORT;
121
    std::string SERVER_IP;
122
    std::string MPD_IP;
123
    std::string MOVIES_DB_PATH;
124
    std::string MENU_PATH;
125
    std::string THREAD_MPD   = "NULL";
126
    std::string THREAD_IRDA  = "NULL";
127
    std::string THREAD_CRON  = "NULL";
128
    std::string THREAD_RS232 = "NULL";
129
    std::string THREAD_DUMMY = "NULL";
130
    std::string TS_KEY= " gg ";
131
    std::string cameraLedON = "";
132
    std::string cameraLedOFF ="";
133
    std::string cameraURL="";
134
    std::string facebookAccessToken = "";
135
    std::string viberToken = "NULL";
136
    std::string viberAvatar;
137
    std::vector <std::string> viberReceiver;
138
    std::string viberSender;
139
    std::string radio433MHzConfigFile;
140
    std::string omxplayerFile = "NULL";
141
    int ID_server = 0;
142
    int v_delay;
143
    bool encrypted = true;
144
145
    FTP_SERVER ftpServer;
146
    std::string lightningApiURL = "NULL";
147
    std::string saveFilePath = "NULL";
148
};
149
150
struct LED_Strip{
151
    std::string from;
152
    std::string to;
153
    std::string R;
154
    std::string G;
155
    std::string B;
156
    std::string colorName;
157
158
    LED_Strip (int from, int to, int r, int g, int b, std::string colorName = "NULL"):from(std::to_string(from)),
159
        to(std::to_string(to)),
160
        R(std::to_string(r)),
161
        G(std::to_string(g)),
162
        B(std::to_string(b)),
163
        colorName(colorName)
164
    {
165
166
    }
167
    LED_Strip (const std::string& from,
168
               const std::string& to,
169
               const std::string& r,
170
               const std::string& g,
171
               const std::string& b,
172
               const std::string& colorName = "NULL"):
173
        from(from),
174
        to(to),
175
        R(r),
176
        G(g),
177
        B(b),
178
        colorName(colorName)
179
    {
180
181
    }
182
183
    void set (const std::string& from,
184
              const std::string& to,
185
              const std::string& r,
186
              const std::string& g,
187
              const std::string& b,
188
              const std::string& colorName = "NULL")
189
    {
190
        this->from =from;
191
        this->to = to;
192
        R = r;
193
        G = g;
194
        B = b;
195
        this->colorName =colorName;
196
    }
197
198
    void set (int from, int to, int r, int g, int b, std::string colorName = "NULL"){
199
        this->from = std::to_string(from);
200
        this->to = std::to_string(to);
201
        R = std::to_string(r);
202
        G = std::to_string(g);
203
        B = std::to_string(b);
204
        this->colorName =colorName;
205
    }
206
207
    std::string getColorName() const{
208
        return colorName;
209
    }
210
211
    std::string get(unsigned int _from, unsigned int _to) const{
212
        if (_from != 0 || _to != 60){
213
            return "LED:["+std::to_string(_from)+"-"+std::to_string(_to)+"-"+R+"-"+G+"-"+B+"];";
214
        }
215
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
216
    }
217
218
    std::string makeCommand(const std::string& from,
219
                            const std::string& to,
220
                            const std::string& R,
221
                            const std::string& G,
222
                            const std::string& B){
223
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
224
    }
225
};
226
227
struct pilot_led{
228
    unsigned int counter=0;
229
    std::vector<LED_Strip> colorLED   = { LED_Strip(1,60,237,145,33 ,"carrot orange"),
230
                                          LED_Strip(1,60,255,0,0    ,"red"),
231
                                          LED_Strip(1,60,0,255,0    ,"green"),
232
                                          LED_Strip(1,60,0,0,255    ,"blue"),
233
                                          LED_Strip(1,60,255,255,255,"white"),
234
                                          LED_Strip(1,60,255,255,0  ,"yellow"),
235
                                          LED_Strip(1,60,0,255,255  ,"cyan"),
236
                                          LED_Strip(1,60,255,0,255  ,"magenta")
237
                                        };
238
};
239
240
class command; // for struc thread_data req
241
class iDomTOOLS;
242
class RADIO_EQ_CONTAINER;
243
class RFLinkHandler;
244
245
struct thread_data{
246
    int s_client_sock;
247
    struct sockaddr_in from;
248
    struct config *server_settings = NULL;
249
    struct s_pointer pointer;
250
    LCD_c *mainLCD = NULL;
251
    files_tree *main_tree = NULL;
252
    menu_tree *main_MENU = NULL;
253
    iDomTOOLS *main_iDomTools = NULL;
254
    RFLinkHandler *main_RFLink = NULL;
255
    std::array<Thread_array_struc, iDomConst::MAX_CONNECTION> *main_THREAD_arr = NULL;
256
    time_t start;
257
    time_t now_time;
258
    int sleeper;
259
    std::map <std::string, std::unique_ptr <KEY> > key_map;
260
    MPD_info *ptr_MPD_info = NULL;
261
    pilot_led * ptr_pilot_led = NULL;
262
    std::map <std::string, std::unique_ptr<command> >* commandMapPtr = NULL;
263
    event_counters_handler myEventHandler;
264
    std::string encriptionKey = "40%";
265
    iDomSTATUS *main_iDomStatus;
266
    iDOM_STATE idom_all_state;
267
    ALERT alarmTime;
268
    std::shared_ptr<RADIO_EQ_CONTAINER> main_REC;
269
    iDomStateEnum iDomProgramState = iDomStateEnum::WORKING;
270
};
271
272
struct thread_data_rs232{
273
    std::string portRS232;
274
    std::string portRS232_clock;
275
    std::string BaudRate;
276
    struct s_pointer pointer;
277
};
278
279
#endif // GLOBAL_H
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDomTools/test/iDomTools_fixture.h
Line
Count
Source
1
#include <gtest/gtest.h>
2
#include "test_data.h"
3
#include "../idomtools.h"
4
#include "../../src/functions/functions.h"
5
#include "../../RADIO_433_eq/radio_433_eq.h"
6
#include "testJSON.h"
7
8
class iDomTOOLS_ClassTest : public ::testing::Test
9
{
10
public:
11
    TEST_JSON test_Json;
12
    LIGHTNING test_lightning;
13
    CARDINAL_DIRECTIONS::ALARM_INFO test_struct;
14
    thread_data test_my_data;
15
    iDomSTATUS test_status;
16
    config test_server_set;
17
    std::shared_ptr<RADIO_EQ_CONTAINER> test_rec;
18
    iDOM_STATE main_iDomStatus;
19
    ALERT test_alarmTime;
20
    pilot_led test_pilot_led;
21
    MPD_info test_ptr_MPD;
22
23
    /// pointer
24
    iDomTOOLS* test_idomTOOLS;
25
    /////// method
26
    iDomTOOLS_ClassTest()//:test_rec(&test_my_data)
27
193
    {
28
193
        std::cout << "konstruktor testu " <<std::endl;
29
193
    }
30
    void SetUp()
31
192
    {
32
192
        std::cout << "SetUP testu iDomTOOLS_ClassTest" <<std::endl;
33
192
        test_rec = std::make_shared<RADIO_EQ_CONTAINER>(&test_my_data);
34
192
        test_server_set.TS_KEY = "key test";
35
192
        test_server_set.viberSender = "test sender";
36
192
        test_server_set.viberReceiver = {"R1","R2"};
37
192
        test_server_set.saveFilePath = "/mnt/ramdisk/iDomStateTest2.save";
38
192
        test_server_set.radio433MHzConfigFile = "/mnt/ramdisk/433_eq_conf.json";
39
192
        test_rec->loadConfig(test_server_set.radio433MHzConfigFile);
40
192
41
192
        test_my_data.main_REC = test_rec;
42
192
        test_my_data.server_settings = &test_server_set;
43
192
        test_my_data.main_iDomStatus = &test_status;
44
192
        test_my_data.alarmTime = test_alarmTime;
45
192
        test_my_data.idom_all_state = main_iDomStatus;
46
192
        test_my_data.ptr_pilot_led = &test_pilot_led;
47
192
48
192
        test_status.addObject("house");
49
192
50
192
        /////////// create
51
192
        test_idomTOOLS = new iDomTOOLS(&test_my_data);
52
192
53
192
        test_my_data.main_iDomTools = test_idomTOOLS;
54
192
        test_ptr_MPD.volume = 3;
55
192
        test_my_data.ptr_MPD_info = &test_ptr_MPD;
56
192
57
192
        useful_F::myStaticData = &test_my_data;
58
192
    }
59
60
    void TearDown()
61
192
    {
62
192
        delete test_idomTOOLS;
63
192
    }
64
};
65
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/logger/logger.hpp
Line
Count
Source
1
/*
2
 * logger.hpp
3
 *
4
 *
5
 * Logger Library Header
6
 *
7
 *
8
 * Copyright (C) 2013-2014  Bryant Moscon - bmoscon@gmail.com
9
 *
10
 * Permission is hereby granted, free of charge, to any person obtaining a copy
11
 * of this software and associated documentation files (the "Software"), to
12
 * deal in the Software without restriction, including without limitation the
13
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
14
 * sell copies of the Software, and to permit persons to whom the Software is
15
 * furnished to do so, subject to the following conditions:
16
 *
17
 * 1. Redistributions of source code must retain the above copyright notice,
18
 *    this list of conditions, and the following disclaimer.
19
 *
20
 * 2. Redistributions in binary form must reproduce the above copyright notice,
21
 *    this list of conditions and the following disclaimer in the documentation
22
 *    and/or other materials provided with the distribution, and in the same
23
 *    place and form as other copyright, license and disclaimer information.
24
 *
25
 * 3. The end-user documentation included with the redistribution, if any, must
26
 *    include the following acknowledgment: "This product includes software
27
 *    developed by Bryant Moscon (http://www.bryantmoscon.org/)", in the same
28
 *    place and form as other third-party acknowledgments. Alternately, this
29
 *    acknowledgment may appear in the software itself, in the same form and
30
 *    location as other such third-party acknowledgments.
31
 *
32
 * 4. Except as contained in this notice, the name of the author, Bryant Moscon,
33
 *    shall not be used in advertising or otherwise to promote the sale, use or
34
 *    other dealings in this Software without prior written authorization from
35
 *    the author.
36
 *
37
 *
38
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
41
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
42
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
44
 * THE SOFTWARE.
45
 *
46
 */
47
#ifndef __LOGGER__
48
#define __LOGGER__
49
50
#include <fstream>
51
#include <cassert>
52
#include <ctime>
53
#include <sstream>
54
55
// Log levels
56
typedef enum {
57
    US =0,
58
    VERBOSE,
59
    DEBUG,
60
    INFO,
61
    WARNING,
62
    ERROR,
63
    CRITICAL,
64
    FATAL
65
} logger_level;
66
67
class Logger : public std::ostringstream {
68
public:
69
70
    explicit Logger(const char *f);
71
    explicit Logger(const std::string& f);
72
    Logger (const Logger &);
73
    Logger &operator= (const Logger &);
74
    ~Logger();
75
    static pthread_mutex_t mutex_log;
76
77
    void set_level(const logger_level& level);
78
    void flush();
79
    void mutex_lock();
80
    void mutex_unlock();
81
82
    template <typename T>
83
    Logger& operator<<(const T& t)
84
12
    {
85
12
        *static_cast<std::ostringstream *>(this) << t;
86
12
        return (*this);
87
12
    }
_ZN6LoggerlsIA22_cEERS_RKT_
Line
Count
Source
84
4
    {
85
4
        *static_cast<std::ostringstream *>(this) << t;
86
4
        return (*this);
87
4
    }
_ZN6LoggerlsIA2_cEERS_RKT_
Line
Count
Source
84
8
    {
85
8
        *static_cast<std::ostringstream *>(this) << t;
86
8
        return (*this);
87
8
    }
88
89
    Logger& operator<<(const logger_level& level);
90
    typedef Logger& (* LoggerManip)(Logger&);
91
    Logger& operator<<(LoggerManip m);
92
93
private:
94
    std::string get_time() const;
95
    inline const char* level_str(const logger_level& level);
96
public:
97
    std::ofstream _file;
98
private:
99
    std::ostream& _log;
100
    logger_level _level;
101
    logger_level _line_level;
102
};
103
104
105
namespace std { 
106
inline Logger& endl(Logger& out)
107
{
108
    out.put('\n');
109
    out.flush();
110
    return (out);
111
}
112
}// end namespace std
113
114
#endif
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDomTools/test/iDom_server_BT.cpp
Line
Count
Source
1
#include <gtest/gtest.h>
2
#include <curl/curl.h>
3
#include "iDomTools_fixture.h"
4
5
class iDom_server_Class : public iDomTOOLS_ClassTest
6
{
7
protected:
8
    TEST_JSON test_Json;
9
    LIGHTNING test_lightning;
10
    CARDINAL_DIRECTIONS::ALARM_INFO test_struct;
11
    virtual void SetUp() final
12
1
    {
13
1
        std::cout << "konfiguracja przed testem iDom_server_Class " <<std::endl;
14
1
    }
15
16
    virtual void TearDown() final
17
1
    {
18
1
        std::cout << "czyszczenie po tescie iDom_server_Class " <<std::endl;
19
1
    }
20
};
21
22
TEST_F(iDom_server_Class, LED_Strip )
23
1
{
24
1
    LED_Strip test_LED("1","60","255","255","255", "WHITE");
25
1
    EXPECT_STREQ(test_LED.getColorName().c_str(), "WHITE");
26
1
    EXPECT_STREQ(test_LED.get(0,60).c_str(),"LED:[1-60-255-255-255];");
27
1
    EXPECT_STREQ(test_LED.makeCommand("1","60","128","128","128").c_str(),"LED:[1-60-128-128-128];");
28
1
29
1
    test_LED.set("1","60","0","255","0","UNKNOWN");
30
1
31
1
    EXPECT_STREQ(test_LED.getColorName().c_str(), "UNKNOWN");
32
1
    EXPECT_STREQ(test_LED.get(0,60).c_str(),"LED:[1-60-0-255-0];");
33
1
34
1
    test_LED.set(50,51,1,2,3,"BLACK");
35
1
36
1
    EXPECT_STREQ(test_LED.getColorName().c_str(), "BLACK");
37
1
    EXPECT_STREQ(test_LED.get(0,60).c_str(),"LED:[50-51-1-2-3];");
38
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/thread_functions/rs232_thread.h
Line
Count
Source (jump to first uncovered line)
1
#ifndef RS232_THREAD_H
2
#define RS232_THREAD_H
3
4
#include "../c_connection/c_connection.h"
5
#include "../TASKER/tasker.h"
6
#include "../SerialPi/serialpi.h"
7
#include "../thread_functions/iDom_thread.h"
8
9
//////////// watek wysylajacy/obdbierajacy dane z portu RS232 ////////
10
4
void Send_Recieve_rs232_thread (thread_data_rs232 *data_rs232, const std::string& threadName){
11
4
12
4
    SerialPi serial_ardu(data_rs232->portRS232);
13
4
    serial_ardu.begin( std::stoi( data_rs232->BaudRate));
14
4
15
4
    log_file_mutex.mutex_lock();
16
4
    log_file_cout << INFO <<"otwarcie portu RS232 " << data_rs232->portRS232 << " " <<data_rs232->BaudRate<<std::endl;
17
4
    log_file_mutex.mutex_unlock();
18
4
19
4
    SerialPi serial_ardu_clock(data_rs232->portRS232_clock);
20
4
    serial_ardu_clock.begin( std::stoi( data_rs232->BaudRate));
21
4
22
4
    log_file_mutex.mutex_lock();
23
4
    log_file_cout << INFO <<"otwarcie portu RS232_clock " << data_rs232->portRS232_clock <<" "<< data_rs232->BaudRate <<std::endl;
24
4
    log_file_mutex.mutex_unlock();
25
4
26
4
    /////////////////////////////////////////////////// RESET ARDUINO AFTER RESTART ////////////////////////////////
27
4
    puts("restart arduino\n");
28
4
    //C_connection::mutex_who.lock();
29
4
    {
30
4
        std::lock_guard<std::mutex> lockWho(useful_F::mutex_who);
31
4
        buffer = "reset:00;";
32
4
        serial_ardu.print(buffer.c_str());
33
4
    }
34
4
    //C_connection::mutex_who.unlock();
35
4
    //puts("test testo po lock");
36
4
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
37
4
    while(useful_F::go_while)
38
4
    {
39
4
        std::this_thread::sleep_for( std::chrono::milliseconds(50));
40
4
        //puts("test testo po lock");
41
4
        { //mutex who
42
4
            std::lock_guard<std::mutex> lockWho(useful_F::mutex_who);
43
4
44
4
            if(data_rs232->pointer.ptr_who[0] == iDomConst::RS232)
45
4
            {
46
1
                std::lock_guard<std::mutex> lockBuf(useful_F::mutex_buf);
47
1
                data_rs232->pointer.ptr_who[0] = data_rs232->pointer.ptr_who[1];
48
1
                data_rs232->pointer.ptr_who[1] = iDomConst::RS232;
49
1
                serial_ardu.print(buffer.c_str());
50
1
51
1
                buffer.erase();
52
1
53
3
                while(useful_F::go_while){
54
3
                    if(serial_ardu.available()>0){
55
3
                        buffer += serial_ardu.read();
56
3
                    }
57
3
                    if(buffer[buffer.size()-1] == ';')
58
3
                    {
59
1
                        buffer.erase(buffer.end()-1);
60
1
                        break;
61
1
                    }
62
3
                }
63
1
#ifdef BT_TEST
64
1
                useful_F::go_while = false;
65
1
                return;
66
1
#endif
67
1
            }
68
4
            else if(data_rs232->pointer.ptr_who[0] == iDomConst::CLOCK)
69
3
            {
70
2
                std::lock_guard<std::mutex> lockBuf(useful_F::mutex_buf);
71
2
                data_rs232->pointer.ptr_who[0] = data_rs232->pointer.ptr_who[1];
72
2
                data_rs232->pointer.ptr_who[1] = iDomConst::CLOCK;
73
2
                serial_ardu_clock.print(buffer.c_str());
74
2
75
2
                buffer.erase();
76
2
77
2
                while(useful_F::go_while){
78
2
                    if(serial_ardu_clock.available()>0)
79
2
                    {
80
1
                        buffer += serial_ardu_clock.read();
81
1
                        buffer += serial_ardu_clock.read();
82
1
                        serial_ardu_clock.flush();
83
1
                        break;
84
1
                    }
85
2
                    else
86
2
                    {
87
1
                        puts("w buforze serial_ardu_clock nie ma avaiable ");
88
1
89
1
                        useful_F::myStaticData->myEventHandler.run("RS232")
90
1
                                ->addEvent("w buforze serial_ardu_clock nie ma avaiable ");
91
1
                        break;
92
1
                    }
93
2
                }
94
2
#ifdef BT_TEST
95
2
                useful_F::go_while = false;
96
2
                return;
97
2
#endif
98
2
            }
99
3
            else if(data_rs232->pointer.ptr_who[0] == iDomConst::FREE)
100
1
            {
101
1
                std::string bufor = "";
102
1
                if(serial_ardu.available()>0) {
103
1
104
5
                    while (useful_F::go_while){
105
5
                        // std::cout << "serial_ardu.available(): "<<serial_ardu.available()<<std::endl;
106
5
                        if(serial_ardu.available()>0){
107
5
                            char t = serial_ardu.read();
108
5
                            // std::cout << "t: "<<t<<std::endl;
109
5
                            if(t == ';'){
110
1
                                serial_ardu.flush();
111
1
                                break;
112
1
                            }
113
5
                            else{
114
4
                                bufor.push_back(t);
115
4
                            }
116
5
                        }
117
5
                    }
118
1
                    useful_F::myStaticData->myEventHandler.run("RS232")->addEvent(bufor);
119
1
120
1
                }
121
1
#ifdef BT_TEST
122
1
                useful_F::go_while = false;
123
1
                return;
124
1
#endif
125
1
            }
126
4
127
4
        }
128
4
    }
129
4
    iDOM_THREAD::stop_thread(threadName, useful_F::myStaticData);
130
0
}
131
#endif // RS232_THREAD_H
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDomTools/test/idomTools_BT.cpp
Line
Count
Source
1
#include <gtest/gtest.h>
2
#include <curl/curl.h>
3
4
#include "iDomTools_fixture.h"
5
6
TEST_F(iDomTOOLS_ClassTest, smog)
7
1
{
8
1
    std::string smog = test_idomTOOLS->getSmog();
9
1
    puts(smog.c_str());
10
1
    puts(" smog");
11
1
    ASSERT_GE(smog.size(),1);
12
1
13
1
    unsigned int smog_int = std::stoi(smog);
14
1
    ASSERT_GT(smog_int,1);
15
1
    ASSERT_LT(smog_int,1000);
16
1
}
17
18
TEST_F(iDomTOOLS_ClassTest, hasTemperatureChange)
19
1
{
20
1
    std::cout << "##################################### 0" <<std::endl;
21
1
22
1
    TEST_DATA::return_send_to_arduino = "20.0:-1.0;";
23
1
    test_idomTOOLS->send_temperature_thingSpeak();
24
1
    EXPECT_EQ(test_idomTOOLS->allThermometer.getLastState("outside"),TEMPERATURE_STATE::Under);
25
1
    EXPECT_EQ(test_idomTOOLS->allThermometer.getLastState("inside"),TEMPERATURE_STATE::NoChanges);
26
1
    std::cout << "##################################### 1" <<std::endl;
27
1
28
1
    TEST_DATA::return_send_to_arduino = "25.4:0.0;";
29
1
    test_idomTOOLS->send_temperature_thingSpeak();
30
1
31
1
    EXPECT_EQ(test_idomTOOLS->allThermometer.getLastState("outside"),TEMPERATURE_STATE::NoChanges);
32
1
    EXPECT_EQ(test_idomTOOLS->allThermometer.getLastState("inside"),TEMPERATURE_STATE::Over);
33
1
34
1
    std::cout << "##################################### 2" <<std::endl;
35
1
36
1
    TEST_DATA::return_send_to_arduino = "21.0:1.0;";
37
1
    test_idomTOOLS->send_temperature_thingSpeak();
38
1
    EXPECT_EQ(test_idomTOOLS->allThermometer.getLastState("outside"),TEMPERATURE_STATE::Over);
39
1
    EXPECT_EQ(test_idomTOOLS->allThermometer.getLastState("inside"),TEMPERATURE_STATE::Under);
40
1
41
1
    std::cout << "##################################### 3" <<std::endl;
42
1
    TEST_DATA::return_send_to_arduino = "21.0:5.0;";
43
1
    test_idomTOOLS->send_temperature_thingSpeak();
44
1
    EXPECT_EQ(test_idomTOOLS->allThermometer.getLastState("outside"),TEMPERATURE_STATE::NoChanges);
45
1
    EXPECT_EQ(test_idomTOOLS->allThermometer.getLastState("inside"),TEMPERATURE_STATE::NoChanges);
46
1
47
1
    std::cout << "##################################### 4" <<std::endl;
48
1
    TEST_DATA::return_send_to_arduino = "21.0:4.0;";
49
1
    test_idomTOOLS->send_temperature_thingSpeak();
50
1
    EXPECT_EQ(test_idomTOOLS->allThermometer.getLastState("outside"),TEMPERATURE_STATE::NoChanges);
51
1
    EXPECT_EQ(test_idomTOOLS->allThermometer.getLastState("inside"),TEMPERATURE_STATE::NoChanges);
52
1
    std::cout << "##################################### 5" <<std::endl;
53
1
54
1
    TEST_DATA::return_send_to_arduino = "31.9:11.11;";
55
1
    test_idomTOOLS->send_temperature_thingSpeak();
56
1
    EXPECT_EQ(test_idomTOOLS->allThermometer.getLastState("outside"),TEMPERATURE_STATE::NoChanges);
57
1
    EXPECT_EQ(test_idomTOOLS->allThermometer.getLastState("inside"),TEMPERATURE_STATE::Over);
58
1
    std::cout << "##################################### 6" <<std::endl;
59
1
60
1
    ////// getThermoStats
61
1
62
1
    std::cout <<"WYNIK: " << test_idomTOOLS->getThermoStats("inside") <<std::endl;
63
1
}
64
65
TEST_F(iDomTOOLS_ClassTest, weatherAlert)
66
1
{
67
1
    std::string test_data_from_www = "    <div style=\"margin:0;padding:0;width:350px;font:0.8em Lucida,Arial,sans-seri                                                                  f;background:#FFC\">\
68
1
            <p style=\"margin:1px;padding:1px;text-align:center;background:#FF9;borde \                                                                 r:1px dotted\"><b><a href=\"http://burze.dzis.net?page=wyszukiwarka&amp;miejscowos\                                                                  c=krakow\" target=\"_blank\" style=\"color:#00E\">krakow</a></b>\
69
1
            <i>(50°03'N 19°57'E)</i>\
70
1
            </p>\
71
1
            <dl style=\"margin:1px 1px 0 1px;padding:0;cl                                                                  ear:both;background:#FFD;border:1px dotted;overflow:auto;color:green;text-align:\                                                                  center\">Zarejestrowano 54 wyładowania atmosferyczne w promieniu 300km . Najbliższe 79.76km na zachód.\
72
1
            </dl>\
73
1
            \
74
1
            <dl style=\"margin:1px 1px 0 1px;padding:0;cl                                                                  ear:both;background:#FFD;border:1px dotted;overflow:auto;color:green;text-align:  \                                                                center\">Mróz, brak ostrzeżeń</dl>\
75
1
            \
76
1
            <dl style=\"margin:1px 1px 0 1px;padding:0;clear:both                                                                  ;background:#FFD;border:1px dotted;overflow:auto;color:green;text-align:center\">  \                                                                Upał, brak ostrzeżeń</dl>\
77
1
            \
78
1
            <dl style=\"margin:1px 1px 0 1px;padding:0;clear:both                                                                  ;background:#FFD;border:1px dotted;overflow:auto;color:green;text-align:center\">  \                                                                Wiatr, brak ostrzeżeń</dl>\
79
1
            \
80
1
            <dl style=\"margin:1px 1px 0 1px;padding:0;clear:both                                                                  ;background:#FFD;border:1px dotted;overflow:auto;color:green;text-align:center\">  \                                                                Opady, brak ostrzeżeń</dl>\
81
1
            \
82
1
            <dl style=\"margin:1px 1px 0 1px;padding:0;clear:both                                                                  ;background:#FFD;border:1px dotted;overflow:auto;color:green;text-align:center\">  \                                                                Burze, brak ostrzeżeń</dl>\
83
1
            \
84
1
            <dl style=\"margin:1px 1px 0 1px;padding:0;clear:both                                                                  ;background:#FFD;border:1px dotted;overflow:auto;color:green;text-align:center\">  \                                                                Trąby powietrzne, brak ostrzeżeń</dl>\
85
1
            </div>";
86
1
87
1
88
1
            std::vector<WEATHER_ALER> test_WA;
89
1
    test_WA =  test_idomTOOLS->getAlert(test_data_from_www);
90
2
    EXPECT_EQ(1,test_WA.size()) << "ZŁY ROZMIAR VEKTORA WA";
91
1
}
92
93
1
TEST_F(iDomTOOLS_ClassTest, send_temperature_thingSpeak){
94
1
95
1
    TEST_DATA::return_send_to_arduino = "-2.3:-2";
96
1
    TEST_DATA::return_httpPost_expect = "NULL";
97
1
    EXPECT_STREQ(TEST_DATA::return_httpPost_expect.c_str(),"NULL");
98
1
    test_idomTOOLS->send_temperature_thingSpeak();
99
1
    std::cout << "DATA: "<< TEST_DATA::return_httpPost_expect <<std::endl;
100
1
    EXPECT_STREQ(TEST_DATA::return_httpPost_expect.c_str(),"httpPost");
101
1
}
102
103
TEST_F(iDomTOOLS_ClassTest, checkAlarm)
104
1
{
105
1
    blockQueue test_q;
106
1
    unsigned int fromVol = 48;
107
1
    unsigned int  toVol = 57;
108
1
109
1
    ///////////////////////////////////// to save
110
1
    test_status.setObjectState("house",STATE::UNLOCK);
111
1
    test_status.setObjectState("music", STATE::PLAY);
112
1
    test_status.setObjectState("speakers", STATE::ON);
113
1
    test_my_data.idom_all_state.houseState = STATE::LOCK;
114
1
115
1
    test_status.setObjectState("listwa",STATE::ON);
116
1
117
1
    test_alarmTime.time = Clock::getTime();
118
1
    test_alarmTime.state = STATE::ACTIVE;
119
1
    test_alarmTime.toVolume = 58;
120
1
    test_alarmTime.fromVolume = 48;
121
1
    test_status.setObjectState("alarm", test_alarmTime.state);
122
1
    test_my_data.alarmTime = test_alarmTime;
123
1
    useful_F::myStaticData = &test_my_data;
124
1
125
1
    //////////////////////////////////////////////////////////////
126
1
127
1
    test_my_data.alarmTime.time = Clock::getTime();
128
1
    test_my_data.alarmTime.state = STATE::ACTIVE;
129
1
130
1
    EXPECT_EQ(test_my_data.alarmTime.state, STATE::ACTIVE);
131
1
132
10
    for(unsigned int i = fromVol; i<toVol; ++i)
133
9
    {
134
9
        test_idomTOOLS->checkAlarm();
135
9
        test_q._get();
136
18
        EXPECT_EQ(test_my_data.alarmTime.state, STATE::WORKING)<< "zły stan w for " << i<< " "<< toVol;
137
18
        EXPECT_EQ(test_my_data.ptr_MPD_info->volume, i+1) << "zły poziom glosnosci w for";
138
9
    }
139
1
140
1
    test_idomTOOLS->checkAlarm();
141
1
142
2
    EXPECT_EQ(test_my_data.alarmTime.state, STATE::DEACTIVE) << "nie jest STATE::DEACTIVE";
143
2
    EXPECT_EQ(test_my_data.ptr_MPD_info->volume, toVol)<< "nie inkrementowane?";
144
1
145
1
}
146
147
TEST_F(iDomTOOLS_ClassTest, homeLockPlayStopMusic)
148
1
{
149
1
    ///////////////////////////////////// to save
150
1
    test_status.setObjectState("house",STATE::UNDEFINE);
151
1
    test_status.setObjectState("music", STATE::PLAY);
152
1
    test_status.setObjectState("speakers", STATE::ON);
153
1
    test_my_data.idom_all_state.houseState = STATE::LOCK;
154
1
155
1
    test_status.setObjectState("listwa",STATE::ON);
156
1
157
1
    test_alarmTime.time = Clock::getTime();
158
1
    test_alarmTime.state = STATE::ACTIVE;
159
1
    test_status.setObjectState("alarm", test_alarmTime.state);
160
1
161
1
    blockQueue test_q;
162
1
    test_q._clearAll();
163
1
    EXPECT_EQ(test_q._size(),0);
164
1
    EXPECT_EQ(test_status.getObjectState("house"),STATE::UNDEFINE);
165
1
    test_idomTOOLS->lockHome();
166
1
    EXPECT_EQ(test_status.getObjectState("house"),STATE::LOCK);
167
1
    test_idomTOOLS->MPD_play(&test_my_data);
168
1
    EXPECT_EQ(test_q._size(),0);
169
1
    test_idomTOOLS->unlockHome();
170
1
    EXPECT_EQ(test_status.getObjectState("house"),STATE::UNLOCK);
171
1
    test_idomTOOLS->MPD_play(&test_my_data);
172
1
    EXPECT_EQ(test_q._size(),1);
173
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::PLAY);
174
1
    EXPECT_EQ(test_q._size(),0);
175
1
    test_idomTOOLS->lockHome();
176
1
    EXPECT_EQ(test_status.getObjectState("house"),STATE::LOCK);
177
1
    test_idomTOOLS->MPD_stop();
178
1
    EXPECT_EQ(test_q._size(),1);
179
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::STOP);
180
1
    EXPECT_EQ(test_q._size(),0);
181
1
    EXPECT_EQ(test_status.getObjectState("house"),STATE::LOCK);
182
1
    std::string returnedString = test_status.getAllObjectsStateString();
183
1
    EXPECT_THAT(returnedString, testing::HasSubstr("LOCK"));
184
1
}
185
186
TEST_F(iDomTOOLS_ClassTest, buttonPressed)
187
1
{
188
1
    std::string button433MHz_id = "01e7be";
189
1
    std::string pressedButtonName = test_idomTOOLS->buttonPressed(button433MHz_id);
190
1
    EXPECT_EQ(1, test_my_data.main_REC->getButtonPointerVector().size());
191
1
    EXPECT_STREQ(std::to_string(button433MHz_id).c_str(),
192
1
                 test_my_data.main_REC->getButtonPointerVector().at(0)->getID().c_str());
193
1
    EXPECT_STREQ(pressedButtonName.c_str(), "locker");
194
1
195
1
    EXPECT_THROW(test_idomTOOLS->buttonPressed(button433MHz_id+"a"),
196
1
                 std::string);
197
1
}
198
199
TEST_F(iDomTOOLS_ClassTest, button433MHzPressedAction_lockerUnlock)
200
1
{
201
1
    blockQueue test_q;
202
1
    test_q._clearAll();
203
1
204
1
    test_idomTOOLS->unlockHome();
205
1
    EXPECT_EQ(test_status.getObjectState("house"),STATE::UNLOCK);
206
1
207
4
    for(auto i =0 ; i < 3; ++i){
208
3
        test_idomTOOLS->button433MHzPressedAction("locker");
209
3
    }
210
1
    EXPECT_EQ(test_status.getObjectState("house"),STATE::LOCK);
211
1
212
1
    EXPECT_EQ(test_q._size(),1);
213
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::STOP);
214
1
215
1
}
216
217
TEST_F(iDomTOOLS_ClassTest, button433MHzPressedAction_lockerLock)
218
1
{
219
1
    blockQueue test_q;
220
1
    test_q._clearAll();
221
1
222
2
    EXPECT_EQ(test_status.getObjectState("house"),STATE::UNDEFINE) << "nie jest UNDEFINED";
223
1
224
1
    test_idomTOOLS->button433MHzPressedAction("locker");
225
2
    EXPECT_EQ(test_status.getObjectState("house"),STATE::UNLOCK)<< "nie jest UNLOCK";
226
1
227
1
    EXPECT_EQ(test_q._size(),1);
228
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::PLAY);
229
1
    EXPECT_EQ(test_q._size(),0);
230
1
}
231
232
TEST_F(iDomTOOLS_ClassTest, testCPU_Load)
233
1
{
234
1
    std::cout <<"TEST LOAD" << std::endl;
235
1
    std::cout << test_idomTOOLS->getSystemInfo() << std::endl;
236
1
}
237
TEST_F(iDomTOOLS_ClassTest, stringToCardinalDirectionsEnum)
238
1
{
239
1
    EXPECT_EQ(CARDINAL_DIRECTIONS::stringToCardinalDirectionsEnum("NWWA"),
240
1
              CARDINAL_DIRECTIONS::CARDINAL_DIRECTIONS_ENUM::ERROR);
241
1
    EXPECT_EQ(CARDINAL_DIRECTIONS::stringToCardinalDirectionsEnum("N"),
242
1
              CARDINAL_DIRECTIONS::CARDINAL_DIRECTIONS_ENUM::N);
243
1
}
244
245
TEST_F(iDomTOOLS_ClassTest, cardinalDirectionsEnumToString)
246
1
{
247
1
    EXPECT_STREQ( CARDINAL_DIRECTIONS::cardinalDirectionsEnumToString(CARDINAL_DIRECTIONS::CARDINAL_DIRECTIONS_ENUM::ERROR).c_str(),
248
1
                  "UNKNOWN DIRECTION");
249
1
    EXPECT_STREQ( CARDINAL_DIRECTIONS::cardinalDirectionsEnumToString(CARDINAL_DIRECTIONS::CARDINAL_DIRECTIONS_ENUM::ESE).c_str(),
250
1
                  "ESE");
251
1
}
252
253
TEST_F(iDomTOOLS_ClassTest, saveState_readState)
254
1
{
255
1
    test_status.setObjectState("house",STATE::UNLOCK);
256
1
    //////////////////// mpd
257
1
    test_status.setObjectState("music", STATE::PLAY);
258
1
    test_status.setObjectState("speakers", STATE::ON);
259
1
    test_my_data.idom_all_state.houseState = STATE::LOCK;
260
1
261
1
    test_status.setObjectState("listwa",STATE::ON);
262
1
    test_alarmTime.time = Clock::getTime();
263
1
    test_alarmTime.state = STATE::ACTIVE;
264
1
    test_alarmTime.fromVolume = 0;
265
1
    test_alarmTime.toVolume = 100;
266
1
    test_alarmTime.radioID = 44;
267
1
    test_my_data.alarmTime = test_alarmTime;
268
1
    test_status.setObjectState("alarm", test_alarmTime.state);
269
1
270
1
    test_idomTOOLS->saveState_iDom();
271
1
272
1
    nlohmann::json testJson;
273
1
    std::ifstream i(test_server_set.saveFilePath);
274
1
    i >> testJson;
275
1
    EXPECT_STREQ(test_status.getObjectStateString("music").c_str(),
276
1
                 testJson.at("MPD").at("music").get<std::string>().c_str() );
277
1
    EXPECT_STREQ((test_status.getObjectStateString("alarm")).c_str(),
278
1
                 testJson.at("ALARM").at("alarm").get<std::string>().c_str() );
279
1
    EXPECT_EQ(test_alarmTime.radioID,
280
1
              testJson.at("ALARM").at("radioID").get<int>() );
281
1
    EXPECT_EQ(test_alarmTime.fromVolume,
282
1
              testJson.at("ALARM").at("fromVolume").get<int>() );
283
1
    EXPECT_EQ(test_alarmTime.toVolume,
284
1
              testJson.at("ALARM").at("toVolume").get<int>() );
285
1
    ////////////////////////////////// read
286
1
    test_idomTOOLS->readState_iDom();
287
1
    EXPECT_EQ(test_my_data.alarmTime.state,STATE::ACTIVE);
288
1
289
1
    test_my_data.server_settings->saveFilePath = "null";
290
1
    EXPECT_NO_THROW(test_idomTOOLS->readState_iDom());
291
1
}
292
293
TEST_F(iDomTOOLS_ClassTest, getLightningStruct)
294
1
{
295
1
    LIGHTNING test_lightning;
296
1
    test_struct = test_lightning.lightningAlert(test_Json.jj_lightning);
297
1
298
1
    test_idomTOOLS->setLightningStruct(test_struct);
299
1
300
1
    bool test_result = test_lightning.checkLightningAlert(&test_struct);
301
1
    EXPECT_TRUE(test_result);
302
1
303
1
    auto test_alert_info = test_idomTOOLS->getLightningStruct();
304
1
    EXPECT_EQ(test_alert_info.timestamp,210);
305
1
}
306
TEST_F(iDomTOOLS_ClassTest, checkLightning)
307
1
{
308
1
    test_my_data.server_settings->lightningApiURL = "http://cyniu88.no-ip.pl/test/json/lightning.json";
309
1
    test_idomTOOLS->checkLightning();
310
1
    auto test_alert_info = test_idomTOOLS->getLightningStruct();
311
1
    EXPECT_EQ(test_alert_info.timestamp,210);
312
1
}
313
314
TEST_F(iDomTOOLS_ClassTest, updateTemperatureStats)
315
1
{
316
1
    TEST_DATA::return_send_to_arduino = "12:12";
317
1
    test_idomTOOLS->updateTemperatureStats();
318
1
    TEST_DATA::return_send_to_arduino = "16:16";
319
1
    test_idomTOOLS->updateTemperatureStats();
320
1
321
1
    ////////////// maleje na mieskzaniu
322
1
    TEST_DATA::return_send_to_arduino = "12:16";
323
1
    test_idomTOOLS->updateTemperatureStats();
324
1
    EXPECT_THAT(TEST_DATA::return_viber_msg,testing::HasSubstr("temperatura maleje"));
325
1
    EXPECT_THAT(TEST_DATA::return_viber_msg,testing::HasSubstr("mieszkaniu"));
326
1
327
1
    ////////////// maleje na polu
328
1
    TEST_DATA::return_send_to_arduino = "12:12";
329
1
    test_idomTOOLS->updateTemperatureStats();
330
1
    EXPECT_THAT(TEST_DATA::return_viber_msg,testing::HasSubstr("temperatura maleje"));
331
1
    EXPECT_THAT(TEST_DATA::return_viber_msg,testing::HasSubstr("polu"));
332
1
333
1
    ////////////// rośnie na mieskzaniu
334
1
    TEST_DATA::return_send_to_arduino = "17:12";
335
1
    test_idomTOOLS->updateTemperatureStats();
336
1
    EXPECT_THAT(TEST_DATA::return_viber_msg,testing::HasSubstr("temperatura rośnie"));
337
1
    EXPECT_THAT(TEST_DATA::return_viber_msg,testing::HasSubstr("mieszkaniu"));
338
1
339
1
    ////////////// rośnie na polu
340
1
    TEST_DATA::return_send_to_arduino = "17:17";
341
1
    test_idomTOOLS->updateTemperatureStats();
342
1
    EXPECT_THAT(TEST_DATA::return_viber_msg,testing::HasSubstr("temperatura rośnie"));
343
1
    EXPECT_THAT(TEST_DATA::return_viber_msg,testing::HasSubstr("polu"));
344
1
}
345
346
TEST_F(iDomTOOLS_ClassTest, speakersON_OFF)
347
1
{
348
1
    EXPECT_EQ(test_status.getObjectState("speakers"), STATE::OFF);
349
1
    useful_F::myStaticData->idom_all_state.houseState = STATE::UNLOCK;
350
1
    test_idomTOOLS->turnOnSpeakers();
351
1
    EXPECT_EQ(test_status.getObjectState("speakers"), STATE::ON);
352
1
    test_idomTOOLS->turnOffSpeakers();
353
1
    EXPECT_EQ(test_status.getObjectState("speakers"), STATE::OFF);
354
1
    useful_F::myStaticData->idom_all_state.houseState = STATE::LOCK;
355
1
    test_idomTOOLS->turnOnSpeakers();
356
1
    EXPECT_EQ(test_status.getObjectState("speakers"), STATE::OFF);
357
1
    std::string retStr = useful_F::myStaticData->myEventHandler.run("speakers")->getEvent();
358
1
    EXPECT_THAT(retStr, testing::HasSubstr("speakers can not start due to home state: LOCK"));
359
1
}
360
361
TEST_F(iDomTOOLS_ClassTest, printerON_OFF)
362
1
{
363
1
    useful_F::myStaticData->idom_all_state.houseState = STATE::UNLOCK;
364
1
    test_idomTOOLS->turnOnPrinter();
365
1
    EXPECT_EQ(test_status.getObjectState("printer"), STATE::ON);
366
1
    test_idomTOOLS->turnOffPrinter();
367
1
    EXPECT_EQ(test_status.getObjectState("printer"), STATE::OFF);
368
1
    useful_F::myStaticData->idom_all_state.houseState = STATE::LOCK;
369
1
    test_idomTOOLS->turnOnPrinter();
370
1
    EXPECT_EQ(test_status.getObjectState("printer"), STATE::OFF);
371
1
    std::string retStr = useful_F::myStaticData->myEventHandler.run("230V")->getEvent();
372
1
    EXPECT_THAT(retStr, testing::HasSubstr("Printer can not start due to home state: LOCK"));
373
1
}
374
375
TEST_F(iDomTOOLS_ClassTest, getPinState)
376
1
{
377
1
    setReturnPinState(0);
378
1
    EXPECT_EQ(test_idomTOOLS->getPinState(0), PIN_STATE::LOW_STATE);
379
1
    setReturnPinState(1);
380
1
    EXPECT_EQ(test_idomTOOLS->getPinState(0), PIN_STATE::HIGH_STATE);
381
1
    setReturnPinState(4);
382
1
    EXPECT_EQ(test_idomTOOLS->getPinState(0), PIN_STATE::UNKNOWN_STATE);
383
1
}
384
385
TEST_F(iDomTOOLS_ClassTest, turnOnOffPrinter)
386
1
{
387
1
    useful_F::myStaticData->idom_all_state.houseState = STATE::UNLOCK;
388
1
    test_status.setObjectState("printer",STATE::ON);
389
1
    EXPECT_EQ(test_status.getObjectState("printer"), STATE::ON);
390
1
    setReturnPinState(1);
391
1
    puts("off printer");
392
1
    test_idomTOOLS->turnOnOffPrinter();
393
1
    EXPECT_EQ(test_status.getObjectState("printer"), STATE::OFF);
394
1
    setReturnPinState(0);
395
1
    puts("on printer");
396
1
    test_idomTOOLS->turnOnOffPrinter();
397
1
    EXPECT_EQ(test_status.getObjectState("printer"), STATE::ON);
398
1
    setReturnPinState(4);
399
1
    test_idomTOOLS->turnOnOffPrinter();
400
1
    EXPECT_EQ(test_status.getObjectState("printer"), STATE::ON);
401
1
}
402
403
TEST_F(iDomTOOLS_ClassTest, turn_On_Off_433MHzSwitch)
404
1
{
405
1
    useful_F::myStaticData->idom_all_state.houseState = STATE::UNLOCK;
406
1
    EXPECT_EQ(test_status.getObjectState("B"),STATE::UNKNOWN);
407
1
    test_idomTOOLS->turnOn433MHzSwitch("B");
408
1
    EXPECT_EQ(test_status.getObjectState("B"),STATE::ON);
409
1
    test_idomTOOLS->turnOff433MHzSwitch("B");
410
1
    EXPECT_EQ(test_status.getObjectState("B"),STATE::OFF);
411
1
}
412
413
TEST_F(iDomTOOLS_ClassTest, turnOnOff433MHzSwitch)
414
1
{
415
1
    useful_F::myStaticData->idom_all_state.houseState = STATE::UNLOCK;
416
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("B"),STATE::UNKNOWN);
417
1
    test_my_data.main_iDomStatus->setObjectState("B",STATE::ON);
418
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("B"),STATE::ON);
419
1
    test_idomTOOLS->turnOnOff433MHzSwitch("B");
420
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("B"),STATE::OFF);
421
1
    test_idomTOOLS->turnOnOff433MHzSwitch("B");
422
1
    EXPECT_EQ(test_status.getObjectState("B"),STATE::ON);
423
1
424
1
}
425
426
TEST_F(iDomTOOLS_ClassTest, runOnSunset)
427
1
{
428
1
    useful_F::myStaticData->idom_all_state.houseState = STATE::LOCK;
429
1
    test_idomTOOLS->runOnSunset();
430
1
    std::string retStr = useful_F::myStaticData->myEventHandler.run("iDom")->getEvent();
431
1
    EXPECT_THAT(retStr, testing::HasSubstr("433MHz can not start due to home state: LOCK"));
432
1
433
1
    useful_F::myStaticData->idom_all_state.houseState = STATE::UNLOCK;
434
1
    auto ptr = static_cast<RADIO_SWITCH*>(test_my_data.main_REC->getEqPointer("B"));
435
1
    ptr->m_state = STATE::ON;
436
1
    test_idomTOOLS->runOnSunset();
437
1
438
1
    EXPECT_EQ(test_my_data.main_REC->getEqPointer("B")->getState(), STATE::OFF);
439
1
440
1
    RADIO_EQ_CONFIG cfg;
441
1
    cfg.sunset = "on";
442
1
    cfg.sunrise = "off";
443
1
444
1
    ptr->setCode(cfg);
445
1
    ptr->m_state = STATE::OFF;
446
1
    test_idomTOOLS->runOnSunset();
447
1
448
1
    EXPECT_EQ(test_my_data.main_REC->getEqPointer("B")->getState(), STATE::ON);
449
1
}
450
451
TEST_F(iDomTOOLS_ClassTest, runOnSunrise)
452
1
{
453
1
    useful_F::myStaticData->idom_all_state.houseState = STATE::LOCK;
454
1
    test_idomTOOLS->runOnSunrise();
455
1
    std::string retStr = useful_F::myStaticData->myEventHandler.run("iDom")->getEvent();
456
1
    EXPECT_THAT(retStr, testing::HasSubstr("433MHz can not start due to home state: LOCK"));
457
1
458
1
    useful_F::myStaticData->idom_all_state.houseState = STATE::UNLOCK;
459
1
    auto ptr = static_cast<RADIO_SWITCH*>(test_my_data.main_REC->getEqPointer("B"));
460
1
    ptr->m_state = STATE::OFF;
461
1
    test_idomTOOLS->runOnSunrise();
462
1
463
1
    EXPECT_EQ(test_my_data.main_REC->getEqPointer("B")->getState(), STATE::ON);
464
1
465
1
    RADIO_EQ_CONFIG cfg;
466
1
    cfg.sunset = "off";
467
1
    cfg.sunrise = "on";
468
1
469
1
    ptr->setCode(cfg);
470
1
471
1
    cfg.sunset = "on";
472
1
    cfg.sunrise = "off";
473
1
474
1
    ptr->setCode(cfg);
475
1
    ptr->m_state = STATE::ON;
476
1
    test_idomTOOLS->runOnSunrise();
477
1
478
1
    EXPECT_EQ(test_my_data.main_REC->getEqPointer("B")->getState(), STATE::OFF);
479
1
}
480
481
TEST_F(iDomTOOLS_ClassTest, getSunrise_Sunset)
482
1
{
483
1
    std::string ret = test_idomTOOLS->getSunrise();
484
1
    EXPECT_THAT(ret, testing::HasSubstr(":"));
485
1
486
1
    ret = test_idomTOOLS->getSunset();
487
1
    EXPECT_THAT(ret, testing::HasSubstr(":"));
488
1
489
1
    ret = test_idomTOOLS->getSunrise(true);
490
1
    EXPECT_THAT(ret, testing::HasSubstr("Sunrise time:"));
491
1
492
1
    ret = test_idomTOOLS->getSunset(true);
493
1
    EXPECT_THAT(ret, testing::HasSubstr("Sunset time:"));
494
1
}
495
496
TEST_F(iDomTOOLS_ClassTest, getDayLenght)
497
1
{
498
1
    std::string ret = test_idomTOOLS->getDayLenght();
499
1
    EXPECT_THAT(ret, testing::HasSubstr(":"));
500
1
501
1
    ret = test_idomTOOLS->getDayLenght(true);
502
1
    EXPECT_THAT(ret, testing::HasSubstr("Day Lenght :"));
503
1
}
504
505
TEST_F(iDomTOOLS_ClassTest, getTextToSpeach)
506
1
{
507
1
    TEST_DATA::return_send_to_arduino = "22:23";
508
1
    std::string ret = test_idomTOOLS->getTextToSpeach();
509
1
    EXPECT_THAT(ret, testing::HasSubstr("Smog:"));
510
1
    std::cout << "TEXT :"<< std::endl << ret << std::endl;
511
1
}
512
513
TEST_F(iDomTOOLS_ClassTest, mpd)
514
1
{
515
1
    MPD_info test_ptr_MPD;
516
1
    test_ptr_MPD.volume = 3;
517
1
    test_my_data.ptr_MPD_info = &test_ptr_MPD;
518
1
    blockQueue test_q;
519
1
    test_q._clearAll();
520
1
    useful_F::myStaticData->idom_all_state.houseState = STATE::LOCK;
521
1
    test_idomTOOLS->MPD_play(&test_my_data);
522
1
    std::string retStr = useful_F::myStaticData->myEventHandler.run("MPD")->getEvent();
523
1
    EXPECT_THAT(retStr, testing::HasSubstr("MPD can not start due to home state: LOCK"));
524
1
    EXPECT_EQ(test_q._size(), 0);
525
1
526
1
    useful_F::myStaticData->idom_all_state.houseState = STATE::UNLOCK;
527
1
    test_idomTOOLS->MPD_play(&test_my_data);
528
1
    EXPECT_EQ(test_q._size(), 1);
529
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::PLAY);
530
1
    EXPECT_EQ(test_q._size(), 0);
531
1
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
532
1
    useful_F::myStaticData->idom_all_state.houseState = STATE::LOCK;
533
1
534
1
    useful_F::myStaticData->myEventHandler.run("MPD")->clearEvent();
535
1
    test_idomTOOLS->MPD_play(&test_my_data,2);
536
1
    retStr = useful_F::myStaticData->myEventHandler.run("MPD")->getEvent();
537
1
    EXPECT_THAT(retStr, testing::HasSubstr("MPD can not start due to home state: LOCK"));
538
1
    EXPECT_EQ(test_q._size(), 0);
539
1
540
1
    useful_F::myStaticData->idom_all_state.houseState = STATE::UNLOCK;
541
1
    test_idomTOOLS->MPD_play(&test_my_data,2);
542
1
    EXPECT_EQ(test_q._size(), 1);
543
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::PLAY_ID);
544
1
    EXPECT_EQ(test_q._size(), 0);
545
1
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
546
1
547
1
    test_idomTOOLS->MPD_stop();
548
1
    EXPECT_EQ(test_q._size(), 1);
549
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::STOP);
550
1
    EXPECT_EQ(test_q._size(), 0);
551
1
552
1
    test_idomTOOLS->MPD_next();
553
1
    EXPECT_EQ(test_q._size(), 1);
554
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::NEXT);
555
1
    EXPECT_EQ(test_q._size(), 0);
556
1
557
1
    test_idomTOOLS->MPD_prev();
558
1
    EXPECT_EQ(test_q._size(), 1);
559
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::PREV);
560
1
    EXPECT_EQ(test_q._size(), 0);
561
1
562
1
    test_idomTOOLS->MPD_pause();
563
1
    EXPECT_EQ(test_q._size(), 1);
564
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::PAUSE );
565
1
    EXPECT_EQ(test_q._size(), 0);
566
1
567
1
    test_idomTOOLS->MPD_volumeUp();
568
1
    EXPECT_EQ(test_q._size(), 1);
569
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::VOLUP );
570
1
    EXPECT_EQ(test_q._size(), 0);
571
1
572
1
    test_idomTOOLS->MPD_volumeDown();
573
1
    EXPECT_EQ(test_q._size(), 1);
574
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::VOLDOWN );
575
1
    EXPECT_EQ(test_q._size(), 0);
576
1
577
1
    test_idomTOOLS->MPD_volumeSet(&test_my_data, 99);
578
1
    EXPECT_EQ(test_q._size(), 1);
579
1
    EXPECT_EQ(test_q._get(), MPD_COMMAND::VOLSET );
580
1
    EXPECT_EQ(test_q._size(), 0);
581
1
    EXPECT_EQ(test_my_data.ptr_MPD_info->volume, 99);
582
1
583
1
    EXPECT_EQ(test_idomTOOLS->MPD_getVolume(&test_my_data),99);
584
1
585
1
}
586
587
TEST_F(iDomTOOLS_ClassTest, getTemperatureString)
588
1
{
589
1
    TEST_DATA::return_send_to_arduino = "-2:2";
590
1
    EXPECT_STREQ(test_my_data.main_iDomTools->getTemperatureString().c_str(), "-2:2");
591
1
}
592
593
TEST_F(iDomTOOLS_ClassTest, cameraLED)
594
1
{
595
1
    TEST_DATA::return_httpPost = "ok.\n";
596
1
    test_my_data.main_iDomTools->cameraLedOFF("test_link");
597
1
598
1
    ///////////////////////////////at day
599
1
    Clock::setTime_forBT_usage(12,12);
600
1
    test_my_data.main_iDomTools->cameraLedON("test_link");
601
1
602
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("cameraLED"), STATE::OFF);
603
1
    ////////////////////////////////////// at night
604
1
    Clock::setTime_forBT_usage(2,2);
605
1
    test_my_data.main_iDomTools->cameraLedON("test_link");
606
1
607
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("cameraLED"), STATE::ON);
608
1
}
609
610
TEST_F(iDomTOOLS_ClassTest, textToSpeach)
611
1
{
612
1
    test_my_data.ptr_MPD_info->isPlay = true;
613
1
    test_my_data.main_iDomStatus->setObjectState("speakers", STATE::UNDEFINE);
614
1
615
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("speakers"), STATE::UNDEFINE);
616
1
    std::vector<std::string> test_v;
617
1
    test_my_data.main_iDomTools->textToSpeach(&test_v); //empty
618
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("speakers"), STATE::UNDEFINE);
619
1
620
1
    test_v = {"test","msg","clock"};
621
1
    test_my_data.ptr_MPD_info->isPlay = true;
622
1
    test_my_data.main_iDomTools->textToSpeach(&test_v);
623
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("speakers"), STATE::UNDEFINE);
624
1
    test_my_data.ptr_MPD_info->isPlay = false;
625
1
    test_my_data.main_iDomTools->textToSpeach(&test_v);
626
1
    EXPECT_EQ(test_my_data.main_iDomStatus->getObjectState("speakers"), STATE::OFF);
627
1
}
628
629
TEST_F(iDomTOOLS_ClassTest, getWeatherEvent)
630
1
{
631
1
    TEST_DATA::return_httpPost = "httpPost";
632
1
    std::string retStr = test_my_data.main_iDomTools->getWeatherEvent("test",10);
633
1
    EXPECT_STREQ(retStr.c_str(),"httpPost");
634
1
}
635
636
TEST_F(iDomTOOLS_ClassTest, isItDay)
637
1
{
638
1
    Clock::setTime_forBT_usage(12,12);
639
1
    EXPECT_TRUE(test_my_data.main_iDomTools->isItDay());
640
1
    Clock::setTime_forBT_usage(2,12);
641
1
    EXPECT_FALSE(test_my_data.main_iDomTools->isItDay());
642
1
}
643
644
TEST_F(iDomTOOLS_ClassTest, ledClear)
645
1
{
646
1
    TEST_DATA::return_send_to_arduino = "done";
647
1
    std::string retStr = test_my_data.main_iDomTools->ledClear();
648
1
    EXPECT_STREQ(retStr.c_str(),"done");
649
1
}
650
651
TEST_F(iDomTOOLS_ClassTest, getAllDataSunrisesunset)
652
1
{
653
1
    EXPECT_THAT(test_my_data.main_iDomTools->getAllDataSunrisesunset(),
654
1
                testing::HasSubstr("Days until Y2K"));
655
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/thread_functions/TEST/rs232_thread_BT.cpp
Line
Count
Source
1
#include <gtest/gtest.h>
2
#include "../../iDom_server_OOP.h"
3
#include "../rs232_thread.h"
4
#include "test_data.h"
5
#include "../../../iDom_server_OOP/src/iDomTools/test/iDomTools_fixture.h"
6
7
std::mutex useful_F::mutex_buf;
8
std::mutex useful_F::mutex_who;
9
10
std::string buffer;
11
12
class rs232_thread_fixture : public iDomTOOLS_ClassTest
13
{
14
15
};
16
17
TEST_F(rs232_thread_fixture, send_Recieve_rs232_thread_fixture_clock)
18
1
{
19
1
    useful_F::go_while = true;
20
1
    EXPECT_EQ(useful_F::myStaticData->myEventHandler.run("RS232")->howManyEvent(), 0);
21
1
    thread_data_rs232 test_data_rs232;
22
1
    test_data_rs232.BaudRate = "9600";
23
1
    test_data_rs232.portRS232 = "test_port";
24
1
    test_data_rs232.portRS232_clock = "test_port_clock";
25
1
    unsigned int wh[2];
26
1
    test_data_rs232.pointer.ptr_who = wh;
27
1
    test_data_rs232.pointer.ptr_who[0] = iDomConst::CLOCK;
28
1
    test_data_rs232.pointer.ptr_who[1] = iDomConst::FREE;
29
1
    EXPECT_EQ(test_data_rs232.pointer.ptr_who[1], iDomConst::FREE);
30
1
31
1
    SerialPi_set_recv_msg("OK");
32
1
    EXPECT_STREQ(TEST_DATA::serial_b.c_str(),"OK");
33
1
    Send_Recieve_rs232_thread(&test_data_rs232,"RS232_THREAD");
34
1
35
1
    EXPECT_STREQ(TEST_DATA::serial_b.c_str(),"");
36
1
    EXPECT_EQ(test_data_rs232.pointer.ptr_who[1], iDomConst::CLOCK);
37
1
    EXPECT_EQ(useful_F::myStaticData->myEventHandler.run("RS232")->howManyEvent(), 0);
38
1
}
39
40
TEST_F(rs232_thread_fixture, send_Recieve_rs232_thread_clock_empty_answer)
41
1
{
42
1
    useful_F::go_while = true;
43
1
    thread_data_rs232 test_data_rs232;
44
1
    test_data_rs232.BaudRate = "9600";
45
1
    test_data_rs232.portRS232 = "test_port";
46
1
    test_data_rs232.portRS232_clock = "test_port_clock";
47
1
    unsigned int test_who[2] = {iDomConst::CLOCK, iDomConst::FREE};
48
1
    EXPECT_EQ(test_who[1], iDomConst::FREE);
49
1
    test_data_rs232.pointer.ptr_who = test_who;
50
1
    EXPECT_EQ(useful_F::myStaticData->myEventHandler.run("RS232")->howManyEvent(), 0);
51
1
    SerialPi_set_recv_msg("");
52
1
    EXPECT_STREQ(TEST_DATA::serial_b.c_str(),"");
53
1
    Send_Recieve_rs232_thread(&test_data_rs232, "RS232_thread");
54
1
55
1
    EXPECT_STREQ(TEST_DATA::serial_b.c_str(),"");
56
1
    EXPECT_EQ(test_data_rs232.pointer.ptr_who[1], iDomConst::CLOCK);
57
1
    EXPECT_EQ(useful_F::myStaticData->myEventHandler.run("RS232")->howManyEvent(), 1);
58
1
}
59
60
TEST_F(rs232_thread_fixture, send_Recieve_rs232_thread_RS232)
61
1
{
62
1
    useful_F::go_while = true;
63
1
    thread_data_rs232 test_data_rs232;
64
1
    test_data_rs232.BaudRate = "9600";
65
1
    test_data_rs232.portRS232 = "test_port";
66
1
    test_data_rs232.portRS232_clock = "test_port_clock";
67
1
    unsigned int test_who[2] = {iDomConst::RS232, iDomConst::FREE};
68
1
    test_data_rs232.pointer.ptr_who = test_who;
69
1
70
1
    test_data_rs232.pointer.ptr_who[0] = iDomConst::RS232;
71
1
    EXPECT_EQ(test_who[0], iDomConst::RS232);
72
1
    SerialPi_set_recv_msg("OK;");
73
1
    Send_Recieve_rs232_thread(&test_data_rs232,"RS232_thread");
74
1
75
1
    EXPECT_STREQ(TEST_DATA::serial_b.c_str(),"");
76
1
    EXPECT_EQ(test_who[1], iDomConst::RS232);
77
1
}
78
79
TEST_F(rs232_thread_fixture, send_Recieve_rs232_thread_FREE)
80
1
{
81
1
    EXPECT_EQ(useful_F::myStaticData->myEventHandler.run("RS232")->howManyEvent(), 0);
82
1
    useful_F::go_while = true;
83
1
    thread_data_rs232 test_data_rs232;
84
1
    test_data_rs232.BaudRate = "9600";
85
1
    test_data_rs232.portRS232 = "test_port";
86
1
    test_data_rs232.portRS232_clock = "test_port_clock";
87
1
    unsigned int test_who[2] = {iDomConst::FREE, iDomConst::FREE};
88
1
    test_data_rs232.pointer.ptr_who = test_who;
89
1
90
1
    test_data_rs232.pointer.ptr_who[0] = iDomConst::FREE;
91
1
    EXPECT_EQ(test_who[0], iDomConst::FREE);
92
1
    SerialPi_set_recv_msg("TEST;");
93
1
    Send_Recieve_rs232_thread(&test_data_rs232,"RS232_thread");
94
1
95
1
    EXPECT_STREQ(TEST_DATA::serial_b.c_str(),"");
96
1
    EXPECT_EQ(test_who[1], iDomConst::FREE);
97
    EXPECT_EQ(useful_F::myStaticData->myEventHandler.run("RS232")->howManyEvent(), 1);
98
}
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDomTools/test/lightning_BT.cpp
Line
Count
Source
1
#include <gtest/gtest.h>
2
3
#include "test_data.h"
4
#include "testJSON.h"
5
#include "../idomtools.h"
6
7
class lightning_Class : public ::testing::Test
8
{
9
protected:
10
    TEST_JSON test_Json;
11
    LIGHTNING test_lightning;
12
    CARDINAL_DIRECTIONS::ALARM_INFO test_struct;
13
    virtual void SetUp() final
14
5
    {
15
5
        std::cout << "konfiguracja przed testem lightning_Class " <<std::endl;
16
5
    }
17
18
    virtual void TearDown() final
19
5
    {
20
5
        std::cout << "czyszczenie po tescie lightning_Class " <<std::endl;
21
5
    }
22
};
23
24
TEST_F(lightning_Class, lightningAlertOFF)
25
1
{
26
1
    test_struct = test_lightning.lightningAlert(test_Json.jj_noLightning);
27
1
    std::cout <<std::endl << test_struct.data.str();
28
2
    EXPECT_FALSE(test_struct.riseAlarm) << "BRAK ALARMU";
29
1
}
30
31
TEST_F(lightning_Class, lightningAlertON)
32
1
{
33
1
    test_struct = test_lightning.lightningAlert(test_Json.jj_lightning);
34
1
    std::cout <<std::endl << test_struct.data.str();
35
2
    EXPECT_TRUE(test_struct.riseAlarm) << "BRAK ALARMU";
36
1
}
37
38
TEST_F(lightning_Class, checkLightningAlert)
39
1
{
40
1
41
1
    nlohmann::json test_Json2 = useful_F_libs::getJson("http://cyniu88.no-ip.pl/test/json/on_lightning.json");
42
1
    test_struct = test_lightning.lightningAlert(test_Json.jj_noLightning);
43
1
44
1
    bool test_result = test_lightning.checkLightningAlert(&test_struct);
45
1
46
2
    EXPECT_FALSE(test_result) << "BRAK ALARMU 1";
47
1
    test_struct = test_lightning.lightningAlert(test_Json2);
48
1
    test_result = test_lightning.checkLightningAlert(&test_struct);
49
2
    EXPECT_TRUE(test_result) << "BRAK ALARMU 2";
50
1
    test_result = test_lightning.checkLightningAlert(&test_struct);
51
2
    EXPECT_FALSE(test_result) << "BRAK ALARMU 3";
52
1
    test_struct.riseAlarm = false;
53
1
    test_result = test_lightning.checkLightningAlert(&test_struct);
54
2
    EXPECT_FALSE(test_result) << "BRAK ALARMU 4";
55
1
    test_struct.riseAlarm = false;
56
1
    test_result = test_lightning.checkLightningAlert(&test_struct);
57
2
    EXPECT_FALSE(test_result) << "BRAK ALARMU 5";
58
1
}
59
60
TEST_F(lightning_Class, checkLightningAlert_stormCloser)
61
1
{
62
1
    nlohmann::json test_Json2 = useful_F_libs::getJson("http://cyniu88.no-ip.pl/test/json/on_lightning.json");
63
1
64
1
    test_struct = test_lightning.lightningAlert(test_Json.jj_noLightning);
65
1
    bool test_result = test_lightning.checkLightningAlert(&test_struct);
66
2
    EXPECT_FALSE(test_result) << "BRAK ALARMU 1";
67
1
68
1
    test_struct = test_lightning.lightningAlert(test_Json2);
69
1
    test_result = test_lightning.checkLightningAlert(&test_struct);
70
2
    EXPECT_TRUE(test_result) << "BRAK ALARMU 2";
71
1
72
1
    test_result = test_lightning.checkLightningAlert(&test_struct);
73
2
    EXPECT_FALSE(test_result) << "BRAK ALARMU 3";
74
1
75
1
    test_struct = test_lightning.lightningAlert(test_Json.jj_lightning_lt15km);
76
1
    test_result = test_lightning.checkLightningAlert(&test_struct);
77
2
    EXPECT_TRUE(test_result) << "BRAK ALARMU 4";
78
1
79
1
    test_struct = test_lightning.lightningAlert(test_Json.jj_lightning_lt15km);
80
1
    test_result = test_lightning.checkLightningAlert(&test_struct);
81
2
    EXPECT_FALSE(test_result) << "BRAK ALARMU 5";
82
1
83
1
    test_struct = test_lightning.lightningAlert(test_Json.jj_noLightning);
84
1
    test_result = test_lightning.checkLightningAlert(&test_struct);
85
2
    EXPECT_FALSE(test_result) << "BRAK ALARMU 6";
86
1
87
1
    test_struct = test_lightning.lightningAlert(test_Json.jj_lightning_lt15km);
88
1
    test_result = test_lightning.checkLightningAlert(&test_struct);
89
2
    EXPECT_TRUE(test_result) << "BRAK ALARMU 7";
90
1
}
91
92
TEST_F(lightning_Class, oneLightning)
93
1
{
94
1
    test_struct = test_lightning.lightningAlert(test_Json.jj_oneLightning);
95
1
    bool test_result = test_lightning.checkLightningAlert(&test_struct);
96
1
    EXPECT_FALSE(test_result);
97
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/thread_functions/iDom_thread.cpp
Line
Count
Source (jump to first uncovered line)
1
#include "iDom_thread.h"
2
#include "../functions/functions.h"
3
#include <tuple>
4
#include <array>
5
#include <functional>
6
7
std::string iDOM_THREAD::start_thread(const std::string& name,
8
                                      std::function<void(thread_data*,const std::string& threadName)> functionToThread, //void(fn)(thread_data),
9
                                      thread_data* my_data,
10
                                      int thread_socket)
11
5
{
12
5
    int freeSlotID = useful_F::findFreeThreadSlot(my_data->main_THREAD_arr);
13
5
14
5
    if ( freeSlotID != -1)
15
5
    {
16
4
        my_data->main_THREAD_arr->at(freeSlotID).thread = std::thread(functionToThread ,my_data, name);
17
4
18
4
        my_data->main_THREAD_arr->at(freeSlotID).thread_name   = name;
19
4
        my_data->main_THREAD_arr->at(freeSlotID).thread_ID     = my_data->main_THREAD_arr->at(freeSlotID).thread.get_id();
20
4
        my_data->main_THREAD_arr->at(freeSlotID).thread_socket = thread_socket;
21
4
        my_data->main_THREAD_arr->at(freeSlotID).thread.detach();
22
4
23
4
        log_file_mutex.mutex_lock();
24
4
        log_file_cout << INFO << "watek " << name << " wystartowal "<< my_data->main_THREAD_arr->at(freeSlotID).thread_ID << std::endl;
25
4
        log_file_mutex.mutex_unlock();
26
4
27
4
        return "DONE - " + name + " STARTED";
28
4
    }
29
5
    return "not free space to new thread";
30
5
}
31
32
std::string iDOM_THREAD::start_thread_RS232(const std::string &name,
33
                                            std::function<void (thread_data_rs232 *, const std::string &)> functionToThread,
34
                                            thread_data* my_data,
35
                                            thread_data_rs232 *my_data_rs232,
36
                                            int thread_socket)
37
0
{
38
0
    int freeSlotID = useful_F::findFreeThreadSlot(my_data->main_THREAD_arr);
39
0
40
0
    if ( freeSlotID != -1)
41
0
    {
42
0
        my_data->main_THREAD_arr->at(freeSlotID).thread = std::thread(functionToThread ,my_data_rs232, name);
43
0
44
0
        my_data->main_THREAD_arr->at(freeSlotID).thread_name   = name;
45
0
        my_data->main_THREAD_arr->at(freeSlotID).thread_ID     = my_data->main_THREAD_arr->at(freeSlotID).thread.get_id();
46
0
        my_data->main_THREAD_arr->at(freeSlotID).thread_socket = thread_socket;
47
0
        my_data->main_THREAD_arr->at(freeSlotID).thread.detach();
48
0
49
0
        log_file_mutex.mutex_lock();
50
0
        log_file_cout << INFO << "watek " << name << " wystartowal "<< my_data->main_THREAD_arr->at(freeSlotID).thread_ID << std::endl;
51
0
        log_file_mutex.mutex_unlock();
52
0
53
0
        return "DONE - " + name + " STARTED";
54
0
    }
55
0
    return "not free space to new thread";
56
0
}
57
58
void iDOM_THREAD::stop_thread(const std::string& name,
59
                              thread_data* my_data)
60
5
{
61
5
    try
62
5
    {
63
24
        for (int i =0; i< iDomConst::MAX_CONNECTION; ++i)
64
23
        {
65
23
            if (my_data->main_THREAD_arr->at(i).thread_ID == std::this_thread::get_id())
66
23
            {
67
4
                //my_data->main_THREAD_arr[i].thread.detach();
68
4
                my_data->main_THREAD_arr->at(i).thread_name ="  -empty-  ";
69
4
                my_data->main_THREAD_arr->at(i).thread_ID = std::thread::id();
70
4
                my_data->main_THREAD_arr->at(i).thread_socket = 0;
71
4
                break;
72
4
            }
73
23
        }
74
5
    }
75
5
    catch (std::system_error &e)
76
5
    {
77
0
        log_file_mutex.mutex_lock();
78
0
        log_file_cout << ERROR<< "zlapano wyjatek w watku: " << name << ": " << e.what()<< std::endl;
79
0
        log_file_mutex.mutex_unlock();
80
0
    }
81
5
82
5
    log_file_mutex.mutex_lock();
83
5
    log_file_cout << INFO<< "koniec watku: " <<name << std::endl;
84
5
    log_file_mutex.mutex_unlock();
85
5
}
86
87
void iDOM_THREAD::waitUntilAllThreadEnd(thread_data *my_data)
88
0
{
89
0
    int threadCounter = 0;
90
0
    int counter = 20;
91
0
    do{
92
0
        if (--counter == 0){
93
0
            puts("niedoczekalem sie konca watkow");
94
0
            break;
95
0
        }
96
0
        std::this_thread::sleep_for(std::chrono::milliseconds(1500));
97
0
        threadCounter = 0;
98
0
        for(auto i = my_data->main_THREAD_arr->begin(); i < my_data->main_THREAD_arr->end(); ++i)
99
0
        {
100
0
            threadCounter += i->thread_socket;
101
0
            if (i->thread_socket != 0)
102
0
                std::cout << "thread name: "<< i->thread_name << std::endl;
103
0
        }
104
0
        std::cout << "watki pracuja "<<threadCounter<< std::endl;
105
0
    } while(threadCounter != 0);
106
0
}
107
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDom_server_OOP.h
Line
Count
Source
1
#ifndef GLOBAL_H
2
#define GLOBAL_H
3
4
#include <iostream>
5
#include <fstream>
6
#include <string>
7
#include <cstdlib>
8
#include <pthread.h>
9
#include <stdio.h>
10
#include <stdlib.h>
11
#include <sys/socket.h>
12
#include <sys/types.h>
13
#include <netinet/in.h>
14
#include <vector>
15
#include <thread>
16
#include <arpa/inet.h>
17
#include <netinet/in.h>
18
#include <unistd.h>
19
#include <sys/fcntl.h>
20
#include <unistd.h>
21
#include <errno.h>
22
#include <signal.h>
23
#include <time.h>
24
#include <wiringPi.h>
25
#include <chrono>
26
#include <array>
27
28
// MOJE BIBLIOTEKI
29
#include "KEY/key.h"
30
#include "logger/logger.hpp"
31
#include "files_tree/files_tree.h"
32
#include "menu_tree/menu_tree.h"
33
#include "LCD_c/lcd_c.h"
34
#include "command/command.h"
35
#include "../libs/event_counters/event_counters_handler.h"
36
#include "iDomTools/idomtools.h"
37
#include "iDomStatus/idomstatus.h"
38
#include "iDomSaveState/idom_save_state.h"
39
40
416
#define log_file_cout  f_log //std::cout zmien f_log na std::cout i bedzie wypisywac na ekran
41
176
#define log_file_mutex f_log
42
43
enum class iDomStateEnum{
44
    CLOSE = 0,
45
    RELOAD,
46
    ERROR,
47
    WORKING,
48
    HARD_RELOAD
49
};
50
51
namespace iDomConst
52
{
53
constexpr int MAX_CONNECTION = 10;
54
constexpr int FREE  = 1;
55
constexpr int RS232 = 11;
56
constexpr int CLOCK = 12;
57
constexpr int ok    = 0;
58
constexpr int GPIO_SPIK = 21;
59
constexpr int GPIO_PRINTER = 22;
60
constexpr int BUTTON_PIN = 25;
61
}
62
struct ALERT
63
{
64
    Clock time;
65
    STATE state = STATE::DEACTIVE;
66
    unsigned int fromVolume = 48;
67
    unsigned int toVolume = 58;
68
    unsigned int radioID = 8;
69
};
70
71
extern std::string _logfile;
72
extern Logger log_file_mutex;
73
extern std::string buffer;
74
75
enum class TEMPERATURE_STATE;
76
enum class PILOT_KEY;
77
78
struct MPD_info{
79
    std::string title   = "NULL";
80
    std::string radio   = "NULL";
81
    std::string artist  = "NULL";
82
    int volume = 0;
83
    bool isPlay = false;
84
    int currentSongID = 0;
85
    std::vector <std::string> songList = {"NULL"};
86
};
87
struct s_pointer{
88
    unsigned int *ptr_who;
89
    int32_t *ptr_buf;
90
};
91
92
struct Thread_array_struc {
93
    std::thread thread;
94
    std::thread::id thread_ID = std::thread::id(0);
95
    std::string thread_name;
96
    int thread_socket = 0;
97
};
98
99
struct address_another_servers {
100
    int id;
101
    std::string SERVER_IP;
102
};
103
104
struct FTP_SERVER{
105
    std::string URL;
106
    std::string user;
107
    std::string pass;
108
};
109
struct iDOM_STATE{
110
    STATE houseState = STATE::UNDEFINE;
111
112
};
113
114
struct config{
115
    std::string portRS232;
116
    std::string portRS232_clock;
117
    std::string BaudRate;
118
    std::string RFLinkPort;
119
    std::string RFLinkBaudRate;
120
    int PORT;
121
    std::string SERVER_IP;
122
    std::string MPD_IP;
123
    std::string MOVIES_DB_PATH;
124
    std::string MENU_PATH;
125
    std::string THREAD_MPD   = "NULL";
126
    std::string THREAD_IRDA  = "NULL";
127
    std::string THREAD_CRON  = "NULL";
128
    std::string THREAD_RS232 = "NULL";
129
    std::string THREAD_DUMMY = "NULL";
130
    std::string TS_KEY= " gg ";
131
    std::string cameraLedON = "";
132
    std::string cameraLedOFF ="";
133
    std::string cameraURL="";
134
    std::string facebookAccessToken = "";
135
    std::string viberToken = "NULL";
136
    std::string viberAvatar;
137
    std::vector <std::string> viberReceiver;
138
    std::string viberSender;
139
    std::string radio433MHzConfigFile;
140
    std::string omxplayerFile = "NULL";
141
    int ID_server = 0;
142
    int v_delay;
143
    bool encrypted = true;
144
145
    FTP_SERVER ftpServer;
146
    std::string lightningApiURL = "NULL";
147
    std::string saveFilePath = "NULL";
148
};
149
150
struct LED_Strip{
151
    std::string from;
152
    std::string to;
153
    std::string R;
154
    std::string G;
155
    std::string B;
156
    std::string colorName;
157
158
    LED_Strip (int from, int to, int r, int g, int b, std::string colorName = "NULL"):from(std::to_string(from)),
159
        to(std::to_string(to)),
160
        R(std::to_string(r)),
161
        G(std::to_string(g)),
162
        B(std::to_string(b)),
163
        colorName(colorName)
164
1.55k
    {
165
1.55k
166
1.55k
    }
167
    LED_Strip (const std::string& from,
168
               const std::string& to,
169
               const std::string& r,
170
               const std::string& g,
171
               const std::string& b,
172
               const std::string& colorName = "NULL"):
173
        from(from),
174
        to(to),
175
        R(r),
176
        G(g),
177
        B(b),
178
        colorName(colorName)
179
1
    {
180
1
181
1
    }
182
183
    void set (const std::string& from,
184
              const std::string& to,
185
              const std::string& r,
186
              const std::string& g,
187
              const std::string& b,
188
              const std::string& colorName = "NULL")
189
1
    {
190
1
        this->from =from;
191
1
        this->to = to;
192
1
        R = r;
193
1
        G = g;
194
1
        B = b;
195
1
        this->colorName =colorName;
196
1
    }
197
198
1
    void set (int from, int to, int r, int g, int b, std::string colorName = "NULL"){
199
1
        this->from = std::to_string(from);
200
1
        this->to = std::to_string(to);
201
1
        R = std::to_string(r);
202
1
        G = std::to_string(g);
203
1
        B = std::to_string(b);
204
1
        this->colorName =colorName;
205
1
    }
206
207
12
    std::string getColorName() const{
208
12
        return colorName;
209
12
    }
210
211
19
    std::string get(unsigned int _from, unsigned int _to) const{
212
19
        if (_from != 0 || _to != 60){
213
10
            return "LED:["+std::to_string(_from)+"-"+std::to_string(_to)+"-"+R+"-"+G+"-"+B+"];";
214
10
        }
215
9
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
216
9
    }
217
218
    std::string makeCommand(const std::string& from,
219
                            const std::string& to,
220
                            const std::string& R,
221
                            const std::string& G,
222
1
                            const std::string& B){
223
1
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
224
1
    }
225
};
226
227
struct pilot_led{
228
    unsigned int counter=0;
229
    std::vector<LED_Strip> colorLED   = { LED_Strip(1,60,237,145,33 ,"carrot orange"),
230
                                          LED_Strip(1,60,255,0,0    ,"red"),
231
                                          LED_Strip(1,60,0,255,0    ,"green"),
232
                                          LED_Strip(1,60,0,0,255    ,"blue"),
233
                                          LED_Strip(1,60,255,255,255,"white"),
234
                                          LED_Strip(1,60,255,255,0  ,"yellow"),
235
                                          LED_Strip(1,60,0,255,255  ,"cyan"),
236
                                          LED_Strip(1,60,255,0,255  ,"magenta")
237
                                        };
238
};
239
240
class command; // for struc thread_data req
241
class iDomTOOLS;
242
class RADIO_EQ_CONTAINER;
243
class RFLinkHandler;
244
245
struct thread_data{
246
    int s_client_sock;
247
    struct sockaddr_in from;
248
    struct config *server_settings = NULL;
249
    struct s_pointer pointer;
250
    LCD_c *mainLCD = NULL;
251
    files_tree *main_tree = NULL;
252
    menu_tree *main_MENU = NULL;
253
    iDomTOOLS *main_iDomTools = NULL;
254
    RFLinkHandler *main_RFLink = NULL;
255
    std::array<Thread_array_struc, iDomConst::MAX_CONNECTION> *main_THREAD_arr = NULL;
256
    time_t start;
257
    time_t now_time;
258
    int sleeper;
259
    std::map <std::string, std::unique_ptr <KEY> > key_map;
260
    MPD_info *ptr_MPD_info = NULL;
261
    pilot_led * ptr_pilot_led = NULL;
262
    std::map <std::string, std::unique_ptr<command> >* commandMapPtr = NULL;
263
    event_counters_handler myEventHandler;
264
    std::string encriptionKey = "40%";
265
    iDomSTATUS *main_iDomStatus;
266
    iDOM_STATE idom_all_state;
267
    ALERT alarmTime;
268
    std::shared_ptr<RADIO_EQ_CONTAINER> main_REC;
269
    iDomStateEnum iDomProgramState = iDomStateEnum::WORKING;
270
};
271
272
struct thread_data_rs232{
273
    std::string portRS232;
274
    std::string portRS232_clock;
275
    std::string BaudRate;
276
    struct s_pointer pointer;
277
};
278
279
#endif // GLOBAL_H
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/logger/logger.hpp
Line
Count
Source
1
/*
2
 * logger.hpp
3
 *
4
 *
5
 * Logger Library Header
6
 *
7
 *
8
 * Copyright (C) 2013-2014  Bryant Moscon - bmoscon@gmail.com
9
 *
10
 * Permission is hereby granted, free of charge, to any person obtaining a copy
11
 * of this software and associated documentation files (the "Software"), to
12
 * deal in the Software without restriction, including without limitation the
13
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
14
 * sell copies of the Software, and to permit persons to whom the Software is
15
 * furnished to do so, subject to the following conditions:
16
 *
17
 * 1. Redistributions of source code must retain the above copyright notice,
18
 *    this list of conditions, and the following disclaimer.
19
 *
20
 * 2. Redistributions in binary form must reproduce the above copyright notice,
21
 *    this list of conditions and the following disclaimer in the documentation
22
 *    and/or other materials provided with the distribution, and in the same
23
 *    place and form as other copyright, license and disclaimer information.
24
 *
25
 * 3. The end-user documentation included with the redistribution, if any, must
26
 *    include the following acknowledgment: "This product includes software
27
 *    developed by Bryant Moscon (http://www.bryantmoscon.org/)", in the same
28
 *    place and form as other third-party acknowledgments. Alternately, this
29
 *    acknowledgment may appear in the software itself, in the same form and
30
 *    location as other such third-party acknowledgments.
31
 *
32
 * 4. Except as contained in this notice, the name of the author, Bryant Moscon,
33
 *    shall not be used in advertising or otherwise to promote the sale, use or
34
 *    other dealings in this Software without prior written authorization from
35
 *    the author.
36
 *
37
 *
38
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
41
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
42
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
44
 * THE SOFTWARE.
45
 *
46
 */
47
#ifndef __LOGGER__
48
#define __LOGGER__
49
50
#include <fstream>
51
#include <cassert>
52
#include <ctime>
53
#include <sstream>
54
55
// Log levels
56
typedef enum {
57
    US =0,
58
    VERBOSE,
59
    DEBUG,
60
    INFO,
61
    WARNING,
62
    ERROR,
63
    CRITICAL,
64
    FATAL
65
} logger_level;
66
67
class Logger : public std::ostringstream {
68
public:
69
70
    explicit Logger(const char *f);
71
    explicit Logger(const std::string& f);
72
    Logger (const Logger &);
73
    Logger &operator= (const Logger &);
74
    ~Logger();
75
    static pthread_mutex_t mutex_log;
76
77
    void set_level(const logger_level& level);
78
    void flush();
79
    void mutex_lock();
80
    void mutex_unlock();
81
82
    template <typename T>
83
    Logger& operator<<(const T& t)
84
3
    {
85
3
        *static_cast<std::ostringstream *>(this) << t;
86
3
        return (*this);
87
3
    }
_ZN6LoggerlsIA45_cEERS_RKT_
Line
Count
Source
84
2
    {
85
2
        *static_cast<std::ostringstream *>(this) << t;
86
2
        return (*this);
87
2
    }
_ZN6LoggerlsIA10_cEERS_RKT_
Line
Count
Source
84
1
    {
85
1
        *static_cast<std::ostringstream *>(this) << t;
86
1
        return (*this);
87
1
    }
88
89
    Logger& operator<<(const logger_level& level);
90
    typedef Logger& (* LoggerManip)(Logger&);
91
    Logger& operator<<(LoggerManip m);
92
93
private:
94
    std::string get_time() const;
95
    inline const char* level_str(const logger_level& level);
96
public:
97
    std::ofstream _file;
98
private:
99
    std::ostream& _log;
100
    logger_level _level;
101
    logger_level _line_level;
102
};
103
104
105
namespace std { 
106
inline Logger& endl(Logger& out)
107
92
{
108
92
    out.put('\n');
109
92
    out.flush();
110
92
    return (out);
111
92
}
112
}// end namespace std
113
114
#endif
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/logger/logger.cc
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * logger.cc
3
 *
4
 *
5
 * Logger Library
6
 *
7
 *
8
 * Copyright (C) 2013-2014  Bryant Moscon - bmoscon@gmail.com
9
 * 
10
 * Permission is hereby granted, free of charge, to any person obtaining a copy
11
 * of this software and associated documentation files (the "Software"), to 
12
 * deal in the Software without restriction, including without limitation the 
13
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
14
 * sell copies of the Software, and to permit persons to whom the Software is
15
 * furnished to do so, subject to the following conditions:
16
 *
17
 * 1. Redistributions of source code must retain the above copyright notice, 
18
 *    this list of conditions, and the following disclaimer.
19
 *
20
 * 2. Redistributions in binary form must reproduce the above copyright notice, 
21
 *    this list of conditions and the following disclaimer in the documentation 
22
 *    and/or other materials provided with the distribution, and in the same 
23
 *    place and form as other copyright, license and disclaimer information.
24
 *
25
 * 3. The end-user documentation included with the redistribution, if any, must 
26
 *    include the following acknowledgment: "This product includes software 
27
 *    developed by Bryant Moscon (http://www.bryantmoscon.org/)", in the same 
28
 *    place and form as other third-party acknowledgments. Alternately, this 
29
 *    acknowledgment may appear in the software itself, in the same form and 
30
 *    location as other such third-party acknowledgments.
31
 *
32
 * 4. Except as contained in this notice, the name of the author, Bryant Moscon,
33
 *    shall not be used in advertising or otherwise to promote the sale, use or 
34
 *    other dealings in this Software without prior written authorization from 
35
 *    the author.
36
 *
37
 *
38
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
39
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
40
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
41
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
42
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
44
 * THE SOFTWARE.
45
 *
46
 */
47
48
#include "logger.hpp"
49
50
pthread_mutex_t Logger::mutex_log = PTHREAD_MUTEX_INITIALIZER;
51
52
Logger::Logger(const char *f) : _file(f, std::ios::out | std::ios::app), 
53
        _log(_file),
54
        _level(INFO),
55
        _line_level(VERBOSE)
56
0
{
57
0
  assert(_file.is_open());
58
0
}
Unexecuted instantiation: _ZN6LoggerC2EPKc
Unexecuted instantiation: _ZN6LoggerC1EPKc
59
60
61
Logger::Logger(const std::string& f) : _file(f.c_str(), std::ios::out | std::ios::app), 
62
               _log(_file),
63
               _level(INFO),
64
               _line_level(VERBOSE)
65
1
{
66
1
  assert(_file.is_open());
67
1
}
Unexecuted instantiation: _ZN6LoggerC2ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
_ZN6LoggerC1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
Line
Count
Source
65
1
{
66
1
  assert(_file.is_open());
67
1
}
68
69
70
Logger::~Logger()
71
0
{
72
0
  if (_file.is_open()) {
73
0
    _log.flush();
74
0
    _file.close();
75
0
  }
76
0
}
77
78
void Logger::set_level(const logger_level& level)
79
0
{
80
0
  _level = level;
81
0
}  
82
 
83
84
void Logger::flush()
85
92
{
86
92
  if (_line_level >= _level) {
87
80
    _log << get_time() << " -- [" << level_str(_line_level) << "] -- " << str();
88
80
    _log.flush();
89
80
  }
90
12
  else
91
12
  {
92
12
      _log << get_time() << " -- [" << level_str(_line_level) << "] -- " << str();
93
12
      _log.flush();
94
12
  }
95
92
96
92
  str("");
97
92
  _line_level = VERBOSE;
98
92
}
99
100
101
Logger& Logger::operator<<(const logger_level& level)
102
87
{
103
87
  _line_level = level;
104
87
  return (*this);
105
87
}
106
107
108
Logger& Logger::operator<<(LoggerManip m)
109
92
{ 
110
92
  return m(*this);
111
92
}
112
113
114
std::string Logger::get_time() const
115
92
{
116
92
  struct tm *timeinfo;
117
92
  time_t rawtime;
118
92
  char *time_buf;
119
92
  
120
92
  time(&rawtime);
121
92
  timeinfo = localtime(&rawtime);
122
92
  time_buf = asctime(timeinfo);
123
92
  
124
92
  std::string ret(time_buf);
125
92
  if (!ret.empty() && ret[ret.length() - 1] == '\n') {
126
92
    ret.erase(ret.length()-1);
127
92
  }
128
92
  
129
92
  return (ret);
130
92
}
131
132
133
inline const char* Logger::level_str(const logger_level& level)
134
92
{
135
92
  switch (level) {
136
92
  case VERBOSE:
137
7
    return ("VERBOSE ");
138
92
  case DEBUG:
139
5
    return (" DEBUG  ");
140
92
  case INFO:
141
53
    return ("  INFO  ");
142
92
  case WARNING:
143
6
    return ("WARNING ");
144
92
  case ERROR:
145
9
    return (" ERROR  ");
146
92
  case CRITICAL:
147
11
    return ("CRITICAL");
148
92
  case FATAL:
149
1
    return (" FATAL  ");
150
92
  default:
151
0
    assert(false);
152
92
  } 
153
92
}
154
void Logger::mutex_lock()
155
87
{
156
87
    pthread_mutex_lock(&Logger::mutex_log);
157
87
}
158
159
void Logger::mutex_unlock()
160
87
{
161
87
    pthread_mutex_unlock(&Logger::mutex_log);
162
87
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDom_server_OOP.h
Line
Count
Source
1
#ifndef GLOBAL_H
2
#define GLOBAL_H
3
4
#include <iostream>
5
#include <fstream>
6
#include <string>
7
#include <cstdlib>
8
#include <pthread.h>
9
#include <stdio.h>
10
#include <stdlib.h>
11
#include <sys/socket.h>
12
#include <sys/types.h>
13
#include <netinet/in.h>
14
#include <vector>
15
#include <thread>
16
#include <arpa/inet.h>
17
#include <netinet/in.h>
18
#include <unistd.h>
19
#include <sys/fcntl.h>
20
#include <unistd.h>
21
#include <errno.h>
22
#include <signal.h>
23
#include <time.h>
24
#include <wiringPi.h>
25
#include <chrono>
26
#include <array>
27
28
// MOJE BIBLIOTEKI
29
#include "KEY/key.h"
30
#include "logger/logger.hpp"
31
#include "files_tree/files_tree.h"
32
#include "menu_tree/menu_tree.h"
33
#include "LCD_c/lcd_c.h"
34
#include "command/command.h"
35
#include "../libs/event_counters/event_counters_handler.h"
36
#include "iDomTools/idomtools.h"
37
#include "iDomStatus/idomstatus.h"
38
#include "iDomSaveState/idom_save_state.h"
39
40
#define log_file_cout  f_log //std::cout zmien f_log na std::cout i bedzie wypisywac na ekran
41
2
#define log_file_mutex f_log
42
43
enum class iDomStateEnum{
44
    CLOSE = 0,
45
    RELOAD,
46
    ERROR,
47
    WORKING,
48
    HARD_RELOAD
49
};
50
51
namespace iDomConst
52
{
53
constexpr int MAX_CONNECTION = 10;
54
constexpr int FREE  = 1;
55
constexpr int RS232 = 11;
56
constexpr int CLOCK = 12;
57
constexpr int ok    = 0;
58
constexpr int GPIO_SPIK = 21;
59
constexpr int GPIO_PRINTER = 22;
60
constexpr int BUTTON_PIN = 25;
61
}
62
struct ALERT
63
{
64
    Clock time;
65
    STATE state = STATE::DEACTIVE;
66
    unsigned int fromVolume = 48;
67
    unsigned int toVolume = 58;
68
    unsigned int radioID = 8;
69
};
70
71
extern std::string _logfile;
72
extern Logger log_file_mutex;
73
extern std::string buffer;
74
75
enum class TEMPERATURE_STATE;
76
enum class PILOT_KEY;
77
78
struct MPD_info{
79
    std::string title   = "NULL";
80
    std::string radio   = "NULL";
81
    std::string artist  = "NULL";
82
    int volume = 0;
83
    bool isPlay = false;
84
    int currentSongID = 0;
85
    std::vector <std::string> songList = {"NULL"};
86
};
87
struct s_pointer{
88
    unsigned int *ptr_who;
89
    int32_t *ptr_buf;
90
};
91
92
struct Thread_array_struc {
93
    std::thread thread;
94
    std::thread::id thread_ID = std::thread::id(0);
95
    std::string thread_name;
96
    int thread_socket = 0;
97
};
98
99
struct address_another_servers {
100
    int id;
101
    std::string SERVER_IP;
102
};
103
104
struct FTP_SERVER{
105
    std::string URL;
106
    std::string user;
107
    std::string pass;
108
};
109
struct iDOM_STATE{
110
    STATE houseState = STATE::UNDEFINE;
111
112
};
113
114
struct config{
115
    std::string portRS232;
116
    std::string portRS232_clock;
117
    std::string BaudRate;
118
    std::string RFLinkPort;
119
    std::string RFLinkBaudRate;
120
    int PORT;
121
    std::string SERVER_IP;
122
    std::string MPD_IP;
123
    std::string MOVIES_DB_PATH;
124
    std::string MENU_PATH;
125
    std::string THREAD_MPD   = "NULL";
126
    std::string THREAD_IRDA  = "NULL";
127
    std::string THREAD_CRON  = "NULL";
128
    std::string THREAD_RS232 = "NULL";
129
    std::string THREAD_DUMMY = "NULL";
130
    std::string TS_KEY= " gg ";
131
    std::string cameraLedON = "";
132
    std::string cameraLedOFF ="";
133
    std::string cameraURL="";
134
    std::string facebookAccessToken = "";
135
    std::string viberToken = "NULL";
136
    std::string viberAvatar;
137
    std::vector <std::string> viberReceiver;
138
    std::string viberSender;
139
    std::string radio433MHzConfigFile;
140
    std::string omxplayerFile = "NULL";
141
    int ID_server = 0;
142
    int v_delay;
143
    bool encrypted = true;
144
145
    FTP_SERVER ftpServer;
146
    std::string lightningApiURL = "NULL";
147
    std::string saveFilePath = "NULL";
148
};
149
150
struct LED_Strip{
151
    std::string from;
152
    std::string to;
153
    std::string R;
154
    std::string G;
155
    std::string B;
156
    std::string colorName;
157
158
    LED_Strip (int from, int to, int r, int g, int b, std::string colorName = "NULL"):from(std::to_string(from)),
159
        to(std::to_string(to)),
160
        R(std::to_string(r)),
161
        G(std::to_string(g)),
162
        B(std::to_string(b)),
163
        colorName(colorName)
164
    {
165
166
    }
167
    LED_Strip (const std::string& from,
168
               const std::string& to,
169
               const std::string& r,
170
               const std::string& g,
171
               const std::string& b,
172
               const std::string& colorName = "NULL"):
173
        from(from),
174
        to(to),
175
        R(r),
176
        G(g),
177
        B(b),
178
        colorName(colorName)
179
    {
180
181
    }
182
183
    void set (const std::string& from,
184
              const std::string& to,
185
              const std::string& r,
186
              const std::string& g,
187
              const std::string& b,
188
              const std::string& colorName = "NULL")
189
    {
190
        this->from =from;
191
        this->to = to;
192
        R = r;
193
        G = g;
194
        B = b;
195
        this->colorName =colorName;
196
    }
197
198
    void set (int from, int to, int r, int g, int b, std::string colorName = "NULL"){
199
        this->from = std::to_string(from);
200
        this->to = std::to_string(to);
201
        R = std::to_string(r);
202
        G = std::to_string(g);
203
        B = std::to_string(b);
204
        this->colorName =colorName;
205
    }
206
207
    std::string getColorName() const{
208
        return colorName;
209
    }
210
211
    std::string get(unsigned int _from, unsigned int _to) const{
212
        if (_from != 0 || _to != 60){
213
            return "LED:["+std::to_string(_from)+"-"+std::to_string(_to)+"-"+R+"-"+G+"-"+B+"];";
214
        }
215
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
216
    }
217
218
    std::string makeCommand(const std::string& from,
219
                            const std::string& to,
220
                            const std::string& R,
221
                            const std::string& G,
222
                            const std::string& B){
223
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
224
    }
225
};
226
227
struct pilot_led{
228
    unsigned int counter=0;
229
    std::vector<LED_Strip> colorLED   = { LED_Strip(1,60,237,145,33 ,"carrot orange"),
230
                                          LED_Strip(1,60,255,0,0    ,"red"),
231
                                          LED_Strip(1,60,0,255,0    ,"green"),
232
                                          LED_Strip(1,60,0,0,255    ,"blue"),
233
                                          LED_Strip(1,60,255,255,255,"white"),
234
                                          LED_Strip(1,60,255,255,0  ,"yellow"),
235
                                          LED_Strip(1,60,0,255,255  ,"cyan"),
236
                                          LED_Strip(1,60,255,0,255  ,"magenta")
237
                                        };
238
};
239
240
class command; // for struc thread_data req
241
class iDomTOOLS;
242
class RADIO_EQ_CONTAINER;
243
class RFLinkHandler;
244
245
struct thread_data{
246
    int s_client_sock;
247
    struct sockaddr_in from;
248
    struct config *server_settings = NULL;
249
    struct s_pointer pointer;
250
    LCD_c *mainLCD = NULL;
251
    files_tree *main_tree = NULL;
252
    menu_tree *main_MENU = NULL;
253
    iDomTOOLS *main_iDomTools = NULL;
254
    RFLinkHandler *main_RFLink = NULL;
255
    std::array<Thread_array_struc, iDomConst::MAX_CONNECTION> *main_THREAD_arr = NULL;
256
    time_t start;
257
    time_t now_time;
258
    int sleeper;
259
    std::map <std::string, std::unique_ptr <KEY> > key_map;
260
    MPD_info *ptr_MPD_info = NULL;
261
    pilot_led * ptr_pilot_led = NULL;
262
    std::map <std::string, std::unique_ptr<command> >* commandMapPtr = NULL;
263
    event_counters_handler myEventHandler;
264
    std::string encriptionKey = "40%";
265
    iDomSTATUS *main_iDomStatus;
266
    iDOM_STATE idom_all_state;
267
    ALERT alarmTime;
268
    std::shared_ptr<RADIO_EQ_CONTAINER> main_REC;
269
    iDomStateEnum iDomProgramState = iDomStateEnum::WORKING;
270
};
271
272
struct thread_data_rs232{
273
    std::string portRS232;
274
    std::string portRS232_clock;
275
    std::string BaudRate;
276
    struct s_pointer pointer;
277
};
278
279
#endif // GLOBAL_H
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/logger/logger.hpp
Line
Count
Source
1
/*
2
 * logger.hpp
3
 *
4
 *
5
 * Logger Library Header
6
 *
7
 *
8
 * Copyright (C) 2013-2014  Bryant Moscon - bmoscon@gmail.com
9
 *
10
 * Permission is hereby granted, free of charge, to any person obtaining a copy
11
 * of this software and associated documentation files (the "Software"), to
12
 * deal in the Software without restriction, including without limitation the
13
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
14
 * sell copies of the Software, and to permit persons to whom the Software is
15
 * furnished to do so, subject to the following conditions:
16
 *
17
 * 1. Redistributions of source code must retain the above copyright notice,
18
 *    this list of conditions, and the following disclaimer.
19
 *
20
 * 2. Redistributions in binary form must reproduce the above copyright notice,
21
 *    this list of conditions and the following disclaimer in the documentation
22
 *    and/or other materials provided with the distribution, and in the same
23
 *    place and form as other copyright, license and disclaimer information.
24
 *
25
 * 3. The end-user documentation included with the redistribution, if any, must
26
 *    include the following acknowledgment: "This product includes software
27
 *    developed by Bryant Moscon (http://www.bryantmoscon.org/)", in the same
28
 *    place and form as other third-party acknowledgments. Alternately, this
29
 *    acknowledgment may appear in the software itself, in the same form and
30
 *    location as other such third-party acknowledgments.
31
 *
32
 * 4. Except as contained in this notice, the name of the author, Bryant Moscon,
33
 *    shall not be used in advertising or otherwise to promote the sale, use or
34
 *    other dealings in this Software without prior written authorization from
35
 *    the author.
36
 *
37
 *
38
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
41
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
42
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
44
 * THE SOFTWARE.
45
 *
46
 */
47
#ifndef __LOGGER__
48
#define __LOGGER__
49
50
#include <fstream>
51
#include <cassert>
52
#include <ctime>
53
#include <sstream>
54
55
// Log levels
56
typedef enum {
57
    US =0,
58
    VERBOSE,
59
    DEBUG,
60
    INFO,
61
    WARNING,
62
    ERROR,
63
    CRITICAL,
64
    FATAL
65
} logger_level;
66
67
class Logger : public std::ostringstream {
68
public:
69
70
    explicit Logger(const char *f);
71
    explicit Logger(const std::string& f);
72
    Logger (const Logger &);
73
    Logger &operator= (const Logger &);
74
    ~Logger();
75
    static pthread_mutex_t mutex_log;
76
77
    void set_level(const logger_level& level);
78
    void flush();
79
    void mutex_lock();
80
    void mutex_unlock();
81
82
    template <typename T>
83
    Logger& operator<<(const T& t)
84
156
    {
85
156
        *static_cast<std::ostringstream *>(this) << t;
86
156
        return (*this);
87
156
    }
_ZN6LoggerlsIA45_cEERS_RKT_
Line
Count
Source
84
2
    {
85
2
        *static_cast<std::ostringstream *>(this) << t;
86
2
        return (*this);
87
2
    }
_ZN6LoggerlsIA10_cEERS_RKT_
Line
Count
Source
84
1
    {
85
1
        *static_cast<std::ostringstream *>(this) << t;
86
1
        return (*this);
87
1
    }
_ZN6LoggerlsIA30_cEERS_RKT_
Line
Count
Source
84
2
    {
85
2
        *static_cast<std::ostringstream *>(this) << t;
86
2
        return (*this);
87
2
    }
_ZN6LoggerlsIA31_cEERS_RKT_
Line
Count
Source
84
3
    {
85
3
        *static_cast<std::ostringstream *>(this) << t;
86
3
        return (*this);
87
3
    }
_ZN6LoggerlsIA39_cEERS_RKT_
Line
Count
Source
84
2
    {
85
2
        *static_cast<std::ostringstream *>(this) << t;
86
2
        return (*this);
87
2
    }
_ZN6LoggerlsINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEERS_RKT_
Line
Count
Source
84
73
    {
85
73
        *static_cast<std::ostringstream *>(this) << t;
86
73
        return (*this);
87
73
    }
_ZN6LoggerlsIA32_cEERS_RKT_
Line
Count
Source
84
6
    {
85
6
        *static_cast<std::ostringstream *>(this) << t;
86
6
        return (*this);
87
6
    }
_ZN6LoggerlsIA28_cEERS_RKT_
Line
Count
Source
84
4
    {
85
4
        *static_cast<std::ostringstream *>(this) << t;
86
4
        return (*this);
87
4
    }
Unexecuted instantiation: _ZN6LoggerlsIA36_cEERS_RKT_
_ZN6LoggerlsIA47_cEERS_RKT_
Line
Count
Source
84
1
    {
85
1
        *static_cast<std::ostringstream *>(this) << t;
86
1
        return (*this);
87
1
    }
_ZN6LoggerlsIA37_cEERS_RKT_
Line
Count
Source
84
2
    {
85
2
        *static_cast<std::ostringstream *>(this) << t;
86
2
        return (*this);
87
2
    }
Unexecuted instantiation: _ZN6LoggerlsIA44_cEERS_RKT_
_ZN6LoggerlsIA23_cEERS_RKT_
Line
Count
Source
84
4
    {
85
4
        *static_cast<std::ostringstream *>(this) << t;
86
4
        return (*this);
87
4
    }
_ZN6LoggerlsIA14_cEERS_RKT_
Line
Count
Source
84
6
    {
85
6
        *static_cast<std::ostringstream *>(this) << t;
86
6
        return (*this);
87
6
    }
Unexecuted instantiation: _ZN6LoggerlsIA27_cEERS_RKT_
Unexecuted instantiation: _ZN6LoggerlsIiEERS_RKT_
_ZN6LoggerlsIA22_cEERS_RKT_
Line
Count
Source
84
4
    {
85
4
        *static_cast<std::ostringstream *>(this) << t;
86
4
        return (*this);
87
4
    }
_ZN6LoggerlsIA2_cEERS_RKT_
Line
Count
Source
84
8
    {
85
8
        *static_cast<std::ostringstream *>(this) << t;
86
8
        return (*this);
87
8
    }
_ZN6LoggerlsIA7_cEERS_RKT_
Line
Count
Source
84
4
    {
85
4
        *static_cast<std::ostringstream *>(this) << t;
86
4
        return (*this);
87
4
    }
_ZN6LoggerlsINSt6thread2idEEERS_RKT_
Line
Count
Source
84
4
    {
85
4
        *static_cast<std::ostringstream *>(this) << t;
86
4
        return (*this);
87
4
    }
_ZN6LoggerlsIA26_cEERS_RKT_
Line
Count
Source
84
3
    {
85
3
        *static_cast<std::ostringstream *>(this) << t;
86
3
        return (*this);
87
3
    }
_ZN6LoggerlsIA3_cEERS_RKT_
Line
Count
Source
84
1
    {
85
1
        *static_cast<std::ostringstream *>(this) << t;
86
1
        return (*this);
87
1
    }
Unexecuted instantiation: _ZN6LoggerlsIPKcEERS_RKT_
_ZN6LoggerlsIA15_cEERS_RKT_
Line
Count
Source
84
5
    {
85
5
        *static_cast<std::ostringstream *>(this) << t;
86
5
        return (*this);
87
5
    }
_ZN6LoggerlsIA29_cEERS_RKT_
Line
Count
Source
84
2
    {
85
2
        *static_cast<std::ostringstream *>(this) << t;
86
2
        return (*this);
87
2
    }
_ZN6LoggerlsIA25_cEERS_RKT_
Line
Count
Source
84
2
    {
85
2
        *static_cast<std::ostringstream *>(this) << t;
86
2
        return (*this);
87
2
    }
_ZN6LoggerlsIPcEERS_RKT_
Line
Count
Source
84
1
    {
85
1
        *static_cast<std::ostringstream *>(this) << t;
86
1
        return (*this);
87
1
    }
_ZN6LoggerlsIA16_cEERS_RKT_
Line
Count
Source
84
3
    {
85
3
        *static_cast<std::ostringstream *>(this) << t;
86
3
        return (*this);
87
3
    }
_ZN6LoggerlsIbEERS_RKT_
Line
Count
Source
84
2
    {
85
2
        *static_cast<std::ostringstream *>(this) << t;
86
2
        return (*this);
87
2
    }
_ZN6LoggerlsIA20_cEERS_RKT_
Line
Count
Source
84
2
    {
85
2
        *static_cast<std::ostringstream *>(this) << t;
86
2
        return (*this);
87
2
    }
_ZN6LoggerlsIA8_cEERS_RKT_
Line
Count
Source
84
8
    {
85
8
        *static_cast<std::ostringstream *>(this) << t;
86
8
        return (*this);
87
8
    }
_ZN6LoggerlsIA21_cEERS_RKT_
Line
Count
Source
84
1
    {
85
1
        *static_cast<std::ostringstream *>(this) << t;
86
1
        return (*this);
87
1
    }
88
89
    Logger& operator<<(const logger_level& level);
90
    typedef Logger& (* LoggerManip)(Logger&);
91
    Logger& operator<<(LoggerManip m);
92
93
private:
94
    std::string get_time() const;
95
    inline const char* level_str(const logger_level& level);
96
public:
97
    std::ofstream _file;
98
private:
99
    std::ostream& _log;
100
    logger_level _level;
101
    logger_level _line_level;
102
};
103
104
105
namespace std { 
106
inline Logger& endl(Logger& out)
107
92
{
108
92
    out.put('\n');
109
92
    out.flush();
110
92
    return (out);
111
92
}
112
}// end namespace std
113
114
#endif
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/libs/json/single_include/nlohmann/json.hpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
    __ _____ _____ _____
3
 __|  |   __|     |   | |  JSON for Modern C++
4
|  |  |__   |  |  | | | |  version 3.2.0
5
|_____|_____|_____|_|___|  https://github.com/nlohmann/json
6
7
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
8
SPDX-License-Identifier: MIT
9
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
10
11
Permission is hereby  granted, free of charge, to any  person obtaining a copy
12
of this software and associated  documentation files (the "Software"), to deal
13
in the Software  without restriction, including without  limitation the rights
14
to  use, copy,  modify, merge,  publish, distribute,  sublicense, and/or  sell
15
copies  of  the Software,  and  to  permit persons  to  whom  the Software  is
16
furnished to do so, subject to the following conditions:
17
18
The above copyright notice and this permission notice shall be included in all
19
copies or substantial portions of the Software.
20
21
THE SOFTWARE  IS PROVIDED "AS  IS", WITHOUT WARRANTY  OF ANY KIND,  EXPRESS OR
22
IMPLIED,  INCLUDING BUT  NOT  LIMITED TO  THE  WARRANTIES OF  MERCHANTABILITY,
23
FITNESS FOR  A PARTICULAR PURPOSE AND  NONINFRINGEMENT. IN NO EVENT  SHALL THE
24
AUTHORS  OR COPYRIGHT  HOLDERS  BE  LIABLE FOR  ANY  CLAIM,  DAMAGES OR  OTHER
25
LIABILITY, WHETHER IN AN ACTION OF  CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
OUT OF OR IN CONNECTION WITH THE SOFTWARE  OR THE USE OR OTHER DEALINGS IN THE
27
SOFTWARE.
28
*/
29
30
#ifndef NLOHMANN_JSON_HPP
31
#define NLOHMANN_JSON_HPP
32
33
#define NLOHMANN_JSON_VERSION_MAJOR 3
34
#define NLOHMANN_JSON_VERSION_MINOR 2
35
#define NLOHMANN_JSON_VERSION_PATCH 0
36
37
#include <algorithm> // all_of, find, for_each
38
#include <cassert> // assert
39
#include <ciso646> // and, not, or
40
#include <cstddef> // nullptr_t, ptrdiff_t, size_t
41
#include <functional> // hash, less
42
#include <initializer_list> // initializer_list
43
#include <iosfwd> // istream, ostream
44
#include <iterator> // iterator_traits, random_access_iterator_tag
45
#include <numeric> // accumulate
46
#include <string> // string, stoi, to_string
47
#include <utility> // declval, forward, move, pair, swap
48
49
// #include <nlohmann/json_fwd.hpp>
50
#ifndef NLOHMANN_JSON_FWD_HPP
51
#define NLOHMANN_JSON_FWD_HPP
52
53
#include <cstdint> // int64_t, uint64_t
54
#include <map> // map
55
#include <memory> // allocator
56
#include <string> // string
57
#include <vector> // vector
58
59
/*!
60
@brief namespace for Niels Lohmann
61
@see https://github.com/nlohmann
62
@since version 1.0.0
63
*/
64
namespace nlohmann
65
{
66
/*!
67
@brief default JSONSerializer template argument
68
69
This serializer ignores the template arguments and uses ADL
70
([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
71
for serialization.
72
*/
73
template<typename T = void, typename SFINAE = void>
74
struct adl_serializer;
75
76
template<template<typename U, typename V, typename... Args> class ObjectType =
77
         std::map,
78
         template<typename U, typename... Args> class ArrayType = std::vector,
79
         class StringType = std::string, class BooleanType = bool,
80
         class NumberIntegerType = std::int64_t,
81
         class NumberUnsignedType = std::uint64_t,
82
         class NumberFloatType = double,
83
         template<typename U> class AllocatorType = std::allocator,
84
         template<typename T, typename SFINAE = void> class JSONSerializer =
85
         adl_serializer>
86
class basic_json;
87
88
/*!
89
@brief JSON Pointer
90
91
A JSON pointer defines a string syntax for identifying a specific value
92
within a JSON document. It can be used with functions `at` and
93
`operator[]`. Furthermore, JSON pointers are the base for JSON patches.
94
95
@sa [RFC 6901](https://tools.ietf.org/html/rfc6901)
96
97
@since version 2.0.0
98
*/
99
template<typename BasicJsonType>
100
class json_pointer;
101
102
/*!
103
@brief default JSON class
104
105
This type is the default specialization of the @ref basic_json class which
106
uses the standard template types.
107
108
@since version 1.0.0
109
*/
110
using json = basic_json<>;
111
}
112
113
#endif
114
115
// #include <nlohmann/detail/macro_scope.hpp>
116
117
118
// This file contains all internal macro definitions
119
// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
120
121
// exclude unsupported compilers
122
#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
123
    #if defined(__clang__)
124
        #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
125
            #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
126
        #endif
127
    #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
128
        #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40900
129
            #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
130
        #endif
131
    #endif
132
#endif
133
134
// disable float-equal warnings on GCC/clang
135
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
136
    #pragma GCC diagnostic push
137
    #pragma GCC diagnostic ignored "-Wfloat-equal"
138
#endif
139
140
// disable documentation warnings on clang
141
#if defined(__clang__)
142
    #pragma GCC diagnostic push
143
    #pragma GCC diagnostic ignored "-Wdocumentation"
144
#endif
145
146
// allow for portable deprecation warnings
147
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
148
    #define JSON_DEPRECATED __attribute__((deprecated))
149
#elif defined(_MSC_VER)
150
    #define JSON_DEPRECATED __declspec(deprecated)
151
#else
152
    #define JSON_DEPRECATED
153
#endif
154
155
// allow to disable exceptions
156
#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
157
154
    #define JSON_THROW(exception) throw exception
158
12.6k
    #define JSON_TRY try
159
    #define JSON_CATCH(exception) catch(exception)
160
    #define JSON_INTERNAL_CATCH(exception) catch(exception)
161
#else
162
    #define JSON_THROW(exception) std::abort()
163
    #define JSON_TRY if(true)
164
    #define JSON_CATCH(exception) if(false)
165
    #define JSON_INTERNAL_CATCH(exception) if(false)
166
#endif
167
168
// override exception macros
169
#if defined(JSON_THROW_USER)
170
    #undef JSON_THROW
171
    #define JSON_THROW JSON_THROW_USER
172
#endif
173
#if defined(JSON_TRY_USER)
174
    #undef JSON_TRY
175
    #define JSON_TRY JSON_TRY_USER
176
#endif
177
#if defined(JSON_CATCH_USER)
178
    #undef JSON_CATCH
179
    #define JSON_CATCH JSON_CATCH_USER
180
    #undef JSON_INTERNAL_CATCH
181
    #define JSON_INTERNAL_CATCH JSON_CATCH_USER
182
#endif
183
#if defined(JSON_INTERNAL_CATCH_USER)
184
    #undef JSON_INTERNAL_CATCH
185
    #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
186
#endif
187
188
// manual branch prediction
189
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
190
9.05M
    #define JSON_LIKELY(x)      __builtin_expect(!!(x), 1)
191
1.17M
    #define JSON_UNLIKELY(x)    __builtin_expect(!!(x), 0)
192
#else
193
    #define JSON_LIKELY(x)      x
194
    #define JSON_UNLIKELY(x)    x
195
#endif
196
197
// C++ language standard detection
198
#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
199
    #define JSON_HAS_CPP_17
200
    #define JSON_HAS_CPP_14
201
#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
202
    #define JSON_HAS_CPP_14
203
#endif
204
205
// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
206
// may be removed in the future once the class is split.
207
208
#define NLOHMANN_BASIC_JSON_TPL_DECLARATION                                \
209
    template<template<typename, typename, typename...> class ObjectType,   \
210
             template<typename, typename...> class ArrayType,              \
211
             class StringType, class BooleanType, class NumberIntegerType, \
212
             class NumberUnsignedType, class NumberFloatType,              \
213
             template<typename> class AllocatorType,                       \
214
             template<typename, typename = void> class JSONSerializer>
215
216
#define NLOHMANN_BASIC_JSON_TPL                                            \
217
    basic_json<ObjectType, ArrayType, StringType, BooleanType,             \
218
    NumberIntegerType, NumberUnsignedType, NumberFloatType,                \
219
    AllocatorType, JSONSerializer>
220
221
// #include <nlohmann/detail/meta/cpp_future.hpp>
222
223
224
#include <ciso646> // not
225
#include <cstddef> // size_t
226
#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
227
228
namespace nlohmann
229
{
230
namespace detail
231
{
232
// alias templates to reduce boilerplate
233
template<bool B, typename T = void>
234
using enable_if_t = typename std::enable_if<B, T>::type;
235
236
template<typename T>
237
using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
238
239
// implementation of C++14 index_sequence and affiliates
240
// source: https://stackoverflow.com/a/32223343
241
template<std::size_t... Ints>
242
struct index_sequence
243
{
244
    using type = index_sequence;
245
    using value_type = std::size_t;
246
    static constexpr std::size_t size() noexcept
247
    {
248
        return sizeof...(Ints);
249
    }
250
};
251
252
template<class Sequence1, class Sequence2>
253
struct merge_and_renumber;
254
255
template<std::size_t... I1, std::size_t... I2>
256
struct merge_and_renumber<index_sequence<I1...>, index_sequence<I2...>>
257
        : index_sequence < I1..., (sizeof...(I1) + I2)... > {};
258
259
template<std::size_t N>
260
struct make_index_sequence
261
    : merge_and_renumber < typename make_index_sequence < N / 2 >::type,
262
      typename make_index_sequence < N - N / 2 >::type > {};
263
264
template<> struct make_index_sequence<0> : index_sequence<> {};
265
template<> struct make_index_sequence<1> : index_sequence<0> {};
266
267
template<typename... Ts>
268
using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
269
270
// dispatch utility (taken from ranges-v3)
271
template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
272
template<> struct priority_tag<0> {};
273
274
// taken from ranges-v3
275
template<typename T>
276
struct static_const
277
{
278
    static constexpr T value{};
279
};
280
281
template<typename T>
282
constexpr T static_const<T>::value;
283
}
284
}
285
286
// #include <nlohmann/detail/meta/type_traits.hpp>
287
288
289
#include <ciso646> // not
290
#include <limits> // numeric_limits
291
#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
292
#include <utility> // declval
293
294
// #include <nlohmann/json_fwd.hpp>
295
296
// #include <nlohmann/detail/meta/cpp_future.hpp>
297
298
// #include <nlohmann/detail/meta/detected.hpp>
299
300
301
#include <type_traits>
302
303
// #include <nlohmann/detail/meta/void_t.hpp>
304
305
306
namespace nlohmann
307
{
308
namespace detail
309
{
310
template <typename ...Ts> struct make_void
311
{
312
    using type = void;
313
};
314
template <typename ...Ts> using void_t = typename make_void<Ts...>::type;
315
}
316
}
317
318
319
// http://en.cppreference.com/w/cpp/experimental/is_detected
320
namespace nlohmann
321
{
322
namespace detail
323
{
324
struct nonesuch
325
{
326
    nonesuch() = delete;
327
    ~nonesuch() = delete;
328
    nonesuch(nonesuch const&) = delete;
329
    void operator=(nonesuch const&) = delete;
330
};
331
332
template <class Default,
333
          class AlwaysVoid,
334
          template <class...> class Op,
335
          class... Args>
336
struct detector
337
{
338
    using value_t = std::false_type;
339
    using type = Default;
340
};
341
342
template <class Default, template <class...> class Op, class... Args>
343
struct detector<Default, void_t<Op<Args...>>, Op, Args...>
344
{
345
    using value_t = std::true_type;
346
    using type = Op<Args...>;
347
};
348
349
template <template <class...> class Op, class... Args>
350
using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
351
352
template <template <class...> class Op, class... Args>
353
using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
354
355
template <class Default, template <class...> class Op, class... Args>
356
using detected_or = detector<Default, void, Op, Args...>;
357
358
template <class Default, template <class...> class Op, class... Args>
359
using detected_or_t = typename detected_or<Default, Op, Args...>::type;
360
361
template <class Expected, template <class...> class Op, class... Args>
362
using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
363
364
template <class To, template <class...> class Op, class... Args>
365
using is_detected_convertible =
366
    std::is_convertible<detected_t<Op, Args...>, To>;
367
}
368
}
369
370
// #include <nlohmann/detail/macro_scope.hpp>
371
372
373
namespace nlohmann
374
{
375
/*!
376
@brief detail namespace with internal helper functions
377
378
This namespace collects functions that should not be exposed,
379
implementations of some @ref basic_json methods, and meta-programming helpers.
380
381
@since version 2.1.0
382
*/
383
namespace detail
384
{
385
/////////////
386
// helpers //
387
/////////////
388
389
template<typename> struct is_basic_json : std::false_type {};
390
391
NLOHMANN_BASIC_JSON_TPL_DECLARATION
392
struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
393
394
//////////////////////////
395
// aliases for detected //
396
//////////////////////////
397
398
template <typename T>
399
using mapped_type_t = typename T::mapped_type;
400
401
template <typename T>
402
using key_type_t = typename T::key_type;
403
404
template <typename T>
405
using value_type_t = typename T::value_type;
406
407
template <typename T>
408
using difference_type_t = typename T::difference_type;
409
410
template <typename T>
411
using pointer_t = typename T::pointer;
412
413
template <typename T>
414
using reference_t = typename T::reference;
415
416
template <typename T>
417
using iterator_category_t = typename T::iterator_category;
418
419
template <typename T>
420
using iterator_t = typename T::iterator;
421
422
template <typename T, typename... Args>
423
using to_json_function = decltype(T::to_json(std::declval<Args>()...));
424
425
template <typename T, typename... Args>
426
using from_json_function = decltype(T::from_json(std::declval<Args>()...));
427
428
///////////////////
429
// is_ functions //
430
///////////////////
431
432
template <typename T, typename = void>
433
struct is_iterator_traits : std::false_type {};
434
435
template <typename T>
436
struct is_iterator_traits<std::iterator_traits<T>>
437
{
438
  private:
439
    using traits = std::iterator_traits<T>;
440
441
  public:
442
    static constexpr auto value =
443
        is_detected<value_type_t, traits>::value &&
444
        is_detected<difference_type_t, traits>::value &&
445
        is_detected<pointer_t, traits>::value &&
446
        is_detected<iterator_category_t, traits>::value &&
447
        is_detected<reference_t, traits>::value;
448
};
449
450
// source: https://stackoverflow.com/a/37193089/4116453
451
452
template <typename T, typename = void>
453
struct is_complete_type : std::false_type {};
454
455
template <typename T>
456
struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
457
458
template <typename BasicJsonType, typename CompatibleObjectType,
459
          typename = void>
460
struct is_compatible_object_type_impl : std::false_type {};
461
462
template <typename BasicJsonType, typename CompatibleObjectType>
463
struct is_compatible_object_type_impl <
464
    BasicJsonType, CompatibleObjectType,
465
    enable_if_t<is_detected<mapped_type_t, CompatibleObjectType>::value and
466
    is_detected<key_type_t, CompatibleObjectType>::value >>
467
{
468
469
    using object_t = typename BasicJsonType::object_t;
470
471
    // macOS's is_constructible does not play well with nonesuch...
472
    static constexpr bool value =
473
        std::is_constructible<typename object_t::key_type,
474
        typename CompatibleObjectType::key_type>::value and
475
        std::is_constructible<typename object_t::mapped_type,
476
        typename CompatibleObjectType::mapped_type>::value;
477
};
478
479
template <typename BasicJsonType, typename CompatibleObjectType>
480
struct is_compatible_object_type
481
    : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
482
483
template <typename BasicJsonType, typename CompatibleStringType,
484
          typename = void>
485
struct is_compatible_string_type_impl : std::false_type {};
486
487
template <typename BasicJsonType, typename CompatibleStringType>
488
struct is_compatible_string_type_impl <
489
    BasicJsonType, CompatibleStringType,
490
    enable_if_t<is_detected_exact<typename BasicJsonType::string_t::value_type,
491
    value_type_t, CompatibleStringType>::value >>
492
{
493
    static constexpr auto value =
494
        std::is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value;
495
};
496
497
template <typename BasicJsonType, typename CompatibleStringType>
498
struct is_compatible_string_type
499
    : is_compatible_string_type_impl<BasicJsonType, CompatibleStringType> {};
500
501
template <typename BasicJsonType, typename CompatibleArrayType, typename = void>
502
struct is_compatible_array_type_impl : std::false_type {};
503
504
template <typename BasicJsonType, typename CompatibleArrayType>
505
struct is_compatible_array_type_impl <
506
    BasicJsonType, CompatibleArrayType,
507
    enable_if_t<is_detected<value_type_t, CompatibleArrayType>::value and
508
    is_detected<iterator_t, CompatibleArrayType>::value >>
509
{
510
    // This is needed because json_reverse_iterator has a ::iterator type...
511
    // Therefore it is detected as a CompatibleArrayType.
512
    // The real fix would be to have an Iterable concept.
513
    static constexpr bool value = not is_iterator_traits<std::iterator_traits<CompatibleArrayType>>::value;
514
};
515
516
template <typename BasicJsonType, typename CompatibleArrayType>
517
struct is_compatible_array_type
518
    : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
519
520
template <typename RealIntegerType, typename CompatibleNumberIntegerType,
521
          typename = void>
522
struct is_compatible_integer_type_impl : std::false_type {};
523
524
template <typename RealIntegerType, typename CompatibleNumberIntegerType>
525
struct is_compatible_integer_type_impl <
526
    RealIntegerType, CompatibleNumberIntegerType,
527
    enable_if_t<std::is_integral<RealIntegerType>::value and
528
    std::is_integral<CompatibleNumberIntegerType>::value and
529
    not std::is_same<bool, CompatibleNumberIntegerType>::value >>
530
{
531
    // is there an assert somewhere on overflows?
532
    using RealLimits = std::numeric_limits<RealIntegerType>;
533
    using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
534
535
    static constexpr auto value =
536
        std::is_constructible<RealIntegerType,
537
        CompatibleNumberIntegerType>::value and
538
        CompatibleLimits::is_integer and
539
        RealLimits::is_signed == CompatibleLimits::is_signed;
540
};
541
542
template <typename RealIntegerType, typename CompatibleNumberIntegerType>
543
struct is_compatible_integer_type
544
    : is_compatible_integer_type_impl<RealIntegerType,
545
      CompatibleNumberIntegerType> {};
546
547
// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
548
template<typename BasicJsonType, typename T>
549
struct has_from_json
550
{
551
    using serializer = typename BasicJsonType::template json_serializer<T, void>;
552
553
    static constexpr bool value =
554
        is_detected_exact<void, from_json_function, serializer,
555
        const BasicJsonType&, T&>::value;
556
};
557
558
// This trait checks if JSONSerializer<T>::from_json(json const&) exists
559
// this overload is used for non-default-constructible user-defined-types
560
template<typename BasicJsonType, typename T>
561
struct has_non_default_from_json
562
{
563
    using serializer = typename BasicJsonType::template json_serializer<T, void>;
564
565
    static constexpr bool value =
566
        is_detected_exact<T, from_json_function, serializer,
567
        const BasicJsonType&>::value;
568
};
569
570
// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
571
template<typename BasicJsonType, typename T>
572
struct has_to_json
573
{
574
    using serializer = typename BasicJsonType::template json_serializer<T, void>;
575
576
    static constexpr bool value =
577
        is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
578
        T>::value;
579
};
580
581
template <typename BasicJsonType, typename CompatibleType, typename = void>
582
struct is_compatible_type_impl: std::false_type {};
583
584
template <typename BasicJsonType, typename CompatibleType>
585
struct is_compatible_type_impl <
586
    BasicJsonType, CompatibleType,
587
    enable_if_t<is_complete_type<CompatibleType>::value >>
588
{
589
    static constexpr bool value =
590
        has_to_json<BasicJsonType, CompatibleType>::value;
591
};
592
593
template <typename BasicJsonType, typename CompatibleType>
594
struct is_compatible_type
595
    : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
596
}
597
}
598
599
// #include <nlohmann/detail/exceptions.hpp>
600
601
602
#include <exception> // exception
603
#include <stdexcept> // runtime_error
604
#include <string> // to_string
605
606
namespace nlohmann
607
{
608
namespace detail
609
{
610
////////////////
611
// exceptions //
612
////////////////
613
614
/*!
615
@brief general exception of the @ref basic_json class
616
617
This class is an extension of `std::exception` objects with a member @a id for
618
exception ids. It is used as the base class for all exceptions thrown by the
619
@ref basic_json class. This class can hence be used as "wildcard" to catch
620
exceptions.
621
622
Subclasses:
623
- @ref parse_error for exceptions indicating a parse error
624
- @ref invalid_iterator for exceptions indicating errors with iterators
625
- @ref type_error for exceptions indicating executing a member function with
626
                  a wrong type
627
- @ref out_of_range for exceptions indicating access out of the defined range
628
- @ref other_error for exceptions indicating other library errors
629
630
@internal
631
@note To have nothrow-copy-constructible exceptions, we internally use
632
      `std::runtime_error` which can cope with arbitrary-length error messages.
633
      Intermediate strings are built with static functions and then passed to
634
      the actual constructor.
635
@endinternal
636
637
@liveexample{The following code shows how arbitrary library exceptions can be
638
caught.,exception}
639
640
@since version 3.0.0
641
*/
642
class exception : public std::exception
643
{
644
  public:
645
    /// returns the explanatory string
646
    const char* what() const noexcept override
647
0
    {
648
0
        return m.what();
649
0
    }
650
651
    /// the id of the exception
652
    const int id;
653
654
  protected:
655
2
    exception(int id_, const char* what_arg) : id(id_), m(what_arg) {}
656
657
    static std::string name(const std::string& ename, int id_)
658
2
    {
659
2
        return "[json.exception." + ename + "." + std::to_string(id_) + "] ";
660
2
    }
661
662
  private:
663
    /// an exception object as storage for error messages
664
    std::runtime_error m;
665
};
666
667
/*!
668
@brief exception indicating a parse error
669
670
This exception is thrown by the library when a parse error occurs. Parse errors
671
can occur during the deserialization of JSON text, CBOR, MessagePack, as well
672
as when using JSON Patch.
673
674
Member @a byte holds the byte index of the last read character in the input
675
file.
676
677
Exceptions have ids 1xx.
678
679
name / id                      | example message | description
680
------------------------------ | --------------- | -------------------------
681
json.exception.parse_error.101 | parse error at 2: unexpected end of input; expected string literal | This error indicates a syntax error while deserializing a JSON text. The error message describes that an unexpected token (character) was encountered, and the member @a byte indicates the error position.
682
json.exception.parse_error.102 | parse error at 14: missing or wrong low surrogate | JSON uses the `\uxxxx` format to describe Unicode characters. Code points above above 0xFFFF are split into two `\uxxxx` entries ("surrogate pairs"). This error indicates that the surrogate pair is incomplete or contains an invalid code point.
683
json.exception.parse_error.103 | parse error: code points above 0x10FFFF are invalid | Unicode supports code points up to 0x10FFFF. Code points above 0x10FFFF are invalid.
684
json.exception.parse_error.104 | parse error: JSON patch must be an array of objects | [RFC 6902](https://tools.ietf.org/html/rfc6902) requires a JSON Patch document to be a JSON document that represents an array of objects.
685
json.exception.parse_error.105 | parse error: operation must have string member 'op' | An operation of a JSON Patch document must contain exactly one "op" member, whose value indicates the operation to perform. Its value must be one of "add", "remove", "replace", "move", "copy", or "test"; other values are errors.
686
json.exception.parse_error.106 | parse error: array index '01' must not begin with '0' | An array index in a JSON Pointer ([RFC 6901](https://tools.ietf.org/html/rfc6901)) may be `0` or any number without a leading `0`.
687
json.exception.parse_error.107 | parse error: JSON pointer must be empty or begin with '/' - was: 'foo' | A JSON Pointer must be a Unicode string containing a sequence of zero or more reference tokens, each prefixed by a `/` character.
688
json.exception.parse_error.108 | parse error: escape character '~' must be followed with '0' or '1' | In a JSON Pointer, only `~0` and `~1` are valid escape sequences.
689
json.exception.parse_error.109 | parse error: array index 'one' is not a number | A JSON Pointer array index must be a number.
690
json.exception.parse_error.110 | parse error at 1: cannot read 2 bytes from vector | When parsing CBOR or MessagePack, the byte vector ends before the complete value has been read.
691
json.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xF8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read.
692
json.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been read.
693
694
@note For an input with n bytes, 1 is the index of the first character and n+1
695
      is the index of the terminating null byte or the end of file. This also
696
      holds true when reading a byte vector (CBOR or MessagePack).
697
698
@liveexample{The following code shows how a `parse_error` exception can be
699
caught.,parse_error}
700
701
@sa @ref exception for the base class of the library exceptions
702
@sa @ref invalid_iterator for exceptions indicating errors with iterators
703
@sa @ref type_error for exceptions indicating executing a member function with
704
                    a wrong type
705
@sa @ref out_of_range for exceptions indicating access out of the defined range
706
@sa @ref other_error for exceptions indicating other library errors
707
708
@since version 3.0.0
709
*/
710
class parse_error : public exception
711
{
712
  public:
713
    /*!
714
    @brief create a parse error exception
715
    @param[in] id_       the id of the exception
716
    @param[in] byte_     the byte index where the error occurred (or 0 if the
717
                         position cannot be determined)
718
    @param[in] what_arg  the explanatory string
719
    @return parse_error object
720
    */
721
    static parse_error create(int id_, std::size_t byte_, const std::string& what_arg)
722
1
    {
723
1
        std::string w = exception::name("parse_error", id_) + "parse error" +
724
1
                        (byte_ != 0 ? (" at " + std::to_string(byte_)) : "") +
725
1
                        ": " + what_arg;
726
1
        return parse_error(id_, byte_, w.c_str());
727
1
    }
728
729
    /*!
730
    @brief byte index of the parse error
731
732
    The byte index of the last read character in the input file.
733
734
    @note For an input with n bytes, 1 is the index of the first character and
735
          n+1 is the index of the terminating null byte or the end of file.
736
          This also holds true when reading a byte vector (CBOR or MessagePack).
737
    */
738
    const std::size_t byte;
739
740
  private:
741
    parse_error(int id_, std::size_t byte_, const char* what_arg)
742
1
        : exception(id_, what_arg), byte(byte_) {}
743
};
744
745
/*!
746
@brief exception indicating errors with iterators
747
748
This exception is thrown if iterators passed to a library function do not match
749
the expected semantics.
750
751
Exceptions have ids 2xx.
752
753
name / id                           | example message | description
754
----------------------------------- | --------------- | -------------------------
755
json.exception.invalid_iterator.201 | iterators are not compatible | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid.
756
json.exception.invalid_iterator.202 | iterator does not fit current value | In an erase or insert function, the passed iterator @a pos does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion.
757
json.exception.invalid_iterator.203 | iterators do not fit current value | Either iterator passed to function @ref erase(IteratorType first, IteratorType last) does not belong to the JSON value from which values shall be erased. It hence does not define a valid range to delete values from.
758
json.exception.invalid_iterator.204 | iterators out of range | When an iterator range for a primitive type (number, boolean, or string) is passed to a constructor or an erase function, this range has to be exactly (@ref begin(), @ref end()), because this is the only way the single stored value is expressed. All other ranges are invalid.
759
json.exception.invalid_iterator.205 | iterator out of range | When an iterator for a primitive type (number, boolean, or string) is passed to an erase function, the iterator has to be the @ref begin() iterator, because it is the only way to address the stored value. All other iterators are invalid.
760
json.exception.invalid_iterator.206 | cannot construct with iterators from null | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) belong to a JSON null value and hence to not define a valid range.
761
json.exception.invalid_iterator.207 | cannot use key() for non-object iterators | The key() member function can only be used on iterators belonging to a JSON object, because other types do not have a concept of a key.
762
json.exception.invalid_iterator.208 | cannot use operator[] for object iterators | The operator[] to specify a concrete offset cannot be used on iterators belonging to a JSON object, because JSON objects are unordered.
763
json.exception.invalid_iterator.209 | cannot use offsets with object iterators | The offset operators (+, -, +=, -=) cannot be used on iterators belonging to a JSON object, because JSON objects are unordered.
764
json.exception.invalid_iterator.210 | iterators do not fit | The iterator range passed to the insert function are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid.
765
json.exception.invalid_iterator.211 | passed iterators may not belong to container | The iterator range passed to the insert function must not be a subrange of the container to insert to.
766
json.exception.invalid_iterator.212 | cannot compare iterators of different containers | When two iterators are compared, they must belong to the same container.
767
json.exception.invalid_iterator.213 | cannot compare order of object iterators | The order of object iterators cannot be compared, because JSON objects are unordered.
768
json.exception.invalid_iterator.214 | cannot get value | Cannot get value for iterator: Either the iterator belongs to a null value or it is an iterator to a primitive type (number, boolean, or string), but the iterator is different to @ref begin().
769
770
@liveexample{The following code shows how an `invalid_iterator` exception can be
771
caught.,invalid_iterator}
772
773
@sa @ref exception for the base class of the library exceptions
774
@sa @ref parse_error for exceptions indicating a parse error
775
@sa @ref type_error for exceptions indicating executing a member function with
776
                    a wrong type
777
@sa @ref out_of_range for exceptions indicating access out of the defined range
778
@sa @ref other_error for exceptions indicating other library errors
779
780
@since version 3.0.0
781
*/
782
class invalid_iterator : public exception
783
{
784
  public:
785
    static invalid_iterator create(int id_, const std::string& what_arg)
786
0
    {
787
0
        std::string w = exception::name("invalid_iterator", id_) + what_arg;
788
0
        return invalid_iterator(id_, w.c_str());
789
0
    }
790
791
  private:
792
    invalid_iterator(int id_, const char* what_arg)
793
0
        : exception(id_, what_arg) {}
794
};
795
796
/*!
797
@brief exception indicating executing a member function with a wrong type
798
799
This exception is thrown in case of a type error; that is, a library function is
800
executed on a JSON value whose type does not match the expected semantics.
801
802
Exceptions have ids 3xx.
803
804
name / id                     | example message | description
805
----------------------------- | --------------- | -------------------------
806
json.exception.type_error.301 | cannot create object from initializer list | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead.
807
json.exception.type_error.302 | type must be object, but is array | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types.
808
json.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t&.
809
json.exception.type_error.304 | cannot use at() with string | The @ref at() member functions can only be executed for certain JSON types.
810
json.exception.type_error.305 | cannot use operator[] with string | The @ref operator[] member functions can only be executed for certain JSON types.
811
json.exception.type_error.306 | cannot use value() with string | The @ref value() member functions can only be executed for certain JSON types.
812
json.exception.type_error.307 | cannot use erase() with string | The @ref erase() member functions can only be executed for certain JSON types.
813
json.exception.type_error.308 | cannot use push_back() with string | The @ref push_back() and @ref operator+= member functions can only be executed for certain JSON types.
814
json.exception.type_error.309 | cannot use insert() with | The @ref insert() member functions can only be executed for certain JSON types.
815
json.exception.type_error.310 | cannot use swap() with number | The @ref swap() member functions can only be executed for certain JSON types.
816
json.exception.type_error.311 | cannot use emplace_back() with string | The @ref emplace_back() member function can only be executed for certain JSON types.
817
json.exception.type_error.312 | cannot use update() with string | The @ref update() member functions can only be executed for certain JSON types.
818
json.exception.type_error.313 | invalid value to unflatten | The @ref unflatten function converts an object whose keys are JSON Pointers back into an arbitrary nested JSON value. The JSON Pointers must not overlap, because then the resulting value would not be well defined.
819
json.exception.type_error.314 | only objects can be unflattened | The @ref unflatten function only works for an object whose keys are JSON Pointers.
820
json.exception.type_error.315 | values in object must be primitive | The @ref unflatten function only works for an object whose keys are JSON Pointers and whose values are primitive.
821
json.exception.type_error.316 | invalid UTF-8 byte at index 10: 0x7E | The @ref dump function only works with UTF-8 encoded strings; that is, if you assign a `std::string` to a JSON value, make sure it is UTF-8 encoded. |
822
823
@liveexample{The following code shows how a `type_error` exception can be
824
caught.,type_error}
825
826
@sa @ref exception for the base class of the library exceptions
827
@sa @ref parse_error for exceptions indicating a parse error
828
@sa @ref invalid_iterator for exceptions indicating errors with iterators
829
@sa @ref out_of_range for exceptions indicating access out of the defined range
830
@sa @ref other_error for exceptions indicating other library errors
831
832
@since version 3.0.0
833
*/
834
class type_error : public exception
835
{
836
  public:
837
    static type_error create(int id_, const std::string& what_arg)
838
0
    {
839
0
        std::string w = exception::name("type_error", id_) + what_arg;
840
0
        return type_error(id_, w.c_str());
841
0
    }
842
843
  private:
844
0
    type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
845
};
846
847
/*!
848
@brief exception indicating access out of the defined range
849
850
This exception is thrown in case a library function is called on an input
851
parameter that exceeds the expected range, for instance in case of array
852
indices or nonexisting object keys.
853
854
Exceptions have ids 4xx.
855
856
name / id                       | example message | description
857
------------------------------- | --------------- | -------------------------
858
json.exception.out_of_range.401 | array index 3 is out of range | The provided array index @a i is larger than @a size-1.
859
json.exception.out_of_range.402 | array index '-' (3) is out of range | The special array index `-` in a JSON Pointer never describes a valid element of the array, but the index past the end. That is, it can only be used to add elements at this position, but not to read it.
860
json.exception.out_of_range.403 | key 'foo' not found | The provided key was not found in the JSON object.
861
json.exception.out_of_range.404 | unresolved reference token 'foo' | A reference token in a JSON Pointer could not be resolved.
862
json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value.
863
json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF.
864
json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON only supports integers numbers up to 9223372036854775807. |
865
json.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. |
866
867
@liveexample{The following code shows how an `out_of_range` exception can be
868
caught.,out_of_range}
869
870
@sa @ref exception for the base class of the library exceptions
871
@sa @ref parse_error for exceptions indicating a parse error
872
@sa @ref invalid_iterator for exceptions indicating errors with iterators
873
@sa @ref type_error for exceptions indicating executing a member function with
874
                    a wrong type
875
@sa @ref other_error for exceptions indicating other library errors
876
877
@since version 3.0.0
878
*/
879
class out_of_range : public exception
880
{
881
  public:
882
    static out_of_range create(int id_, const std::string& what_arg)
883
1
    {
884
1
        std::string w = exception::name("out_of_range", id_) + what_arg;
885
1
        return out_of_range(id_, w.c_str());
886
1
    }
887
888
  private:
889
1
    out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
890
};
891
892
/*!
893
@brief exception indicating other library errors
894
895
This exception is thrown in case of errors that cannot be classified with the
896
other exception types.
897
898
Exceptions have ids 5xx.
899
900
name / id                      | example message | description
901
------------------------------ | --------------- | -------------------------
902
json.exception.other_error.501 | unsuccessful: {"op":"test","path":"/baz", "value":"bar"} | A JSON Patch operation 'test' failed. The unsuccessful operation is also printed.
903
904
@sa @ref exception for the base class of the library exceptions
905
@sa @ref parse_error for exceptions indicating a parse error
906
@sa @ref invalid_iterator for exceptions indicating errors with iterators
907
@sa @ref type_error for exceptions indicating executing a member function with
908
                    a wrong type
909
@sa @ref out_of_range for exceptions indicating access out of the defined range
910
911
@liveexample{The following code shows how an `other_error` exception can be
912
caught.,other_error}
913
914
@since version 3.0.0
915
*/
916
class other_error : public exception
917
{
918
  public:
919
    static other_error create(int id_, const std::string& what_arg)
920
0
    {
921
0
        std::string w = exception::name("other_error", id_) + what_arg;
922
0
        return other_error(id_, w.c_str());
923
0
    }
924
925
  private:
926
0
    other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
927
};
928
}
929
}
930
931
// #include <nlohmann/detail/value_t.hpp>
932
933
934
#include <array> // array
935
#include <ciso646> // and
936
#include <cstddef> // size_t
937
#include <cstdint> // uint8_t
938
939
namespace nlohmann
940
{
941
namespace detail
942
{
943
///////////////////////////
944
// JSON type enumeration //
945
///////////////////////////
946
947
/*!
948
@brief the JSON type enumeration
949
950
This enumeration collects the different JSON types. It is internally used to
951
distinguish the stored values, and the functions @ref basic_json::is_null(),
952
@ref basic_json::is_object(), @ref basic_json::is_array(),
953
@ref basic_json::is_string(), @ref basic_json::is_boolean(),
954
@ref basic_json::is_number() (with @ref basic_json::is_number_integer(),
955
@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()),
956
@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and
957
@ref basic_json::is_structured() rely on it.
958
959
@note There are three enumeration entries (number_integer, number_unsigned, and
960
number_float), because the library distinguishes these three types for numbers:
961
@ref basic_json::number_unsigned_t is used for unsigned integers,
962
@ref basic_json::number_integer_t is used for signed integers, and
963
@ref basic_json::number_float_t is used for floating-point numbers or to
964
approximate integers which do not fit in the limits of their respective type.
965
966
@sa @ref basic_json::basic_json(const value_t value_type) -- create a JSON
967
value with the default value for a given type
968
969
@since version 1.0.0
970
*/
971
enum class value_t : std::uint8_t
972
{
973
    null,             ///< null value
974
    object,           ///< object (unordered set of name/value pairs)
975
    array,            ///< array (ordered collection of values)
976
    string,           ///< string value
977
    boolean,          ///< boolean value
978
    number_integer,   ///< number value (signed integer)
979
    number_unsigned,  ///< number value (unsigned integer)
980
    number_float,     ///< number value (floating-point)
981
    discarded         ///< discarded by the the parser callback function
982
};
983
984
/*!
985
@brief comparison operator for JSON types
986
987
Returns an ordering that is similar to Python:
988
- order: null < boolean < number < object < array < string
989
- furthermore, each type is not smaller than itself
990
- discarded values are not comparable
991
992
@since version 1.0.0
993
*/
994
inline bool operator<(const value_t lhs, const value_t rhs) noexcept
995
0
{
996
0
    static constexpr std::array<std::uint8_t, 8> order = {{
997
0
            0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
998
0
            1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */
999
0
        }
1000
0
    };
1001
0
1002
0
    const auto l_index = static_cast<std::size_t>(lhs);
1003
0
    const auto r_index = static_cast<std::size_t>(rhs);
1004
0
    return l_index < order.size() and r_index < order.size() and order[l_index] < order[r_index];
1005
0
}
1006
}
1007
}
1008
1009
// #include <nlohmann/detail/conversions/from_json.hpp>
1010
1011
1012
#include <algorithm> // transform
1013
#include <array> // array
1014
#include <ciso646> // and, not
1015
#include <forward_list> // forward_list
1016
#include <iterator> // inserter, front_inserter, end
1017
#include <map> // map
1018
#include <string> // string
1019
#include <tuple> // tuple, make_tuple
1020
#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
1021
#include <unordered_map> // unordered_map
1022
#include <utility> // pair, declval
1023
#include <valarray> // valarray
1024
1025
// #include <nlohmann/detail/exceptions.hpp>
1026
1027
// #include <nlohmann/detail/macro_scope.hpp>
1028
1029
// #include <nlohmann/detail/meta/cpp_future.hpp>
1030
1031
// #include <nlohmann/detail/meta/type_traits.hpp>
1032
1033
// #include <nlohmann/detail/value_t.hpp>
1034
1035
1036
namespace nlohmann
1037
{
1038
namespace detail
1039
{
1040
template<typename BasicJsonType>
1041
void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
1042
{
1043
    if (JSON_UNLIKELY(not j.is_null()))
1044
    {
1045
        JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name())));
1046
    }
1047
    n = nullptr;
1048
}
1049
1050
// overloads for basic_json template parameters
1051
template<typename BasicJsonType, typename ArithmeticType,
1052
         enable_if_t<std::is_arithmetic<ArithmeticType>::value and
1053
                     not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
1054
                     int> = 0>
1055
void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
1056
148
{
1057
148
    switch (static_cast<value_t>(j))
1058
148
    {
1059
148
        case value_t::number_unsigned:
1060
0
        {
1061
0
            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
1062
0
            break;
1063
0
        }
1064
0
        case value_t::number_integer:
1065
0
        {
1066
0
            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
1067
0
            break;
1068
0
        }
1069
148
        case value_t::number_float:
1070
148
        {
1071
148
            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
1072
148
            break;
1073
0
        }
1074
0
1075
0
        default:
1076
0
            JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name())));
1077
148
    }
1078
148
}
1079
1080
template<typename BasicJsonType>
1081
void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
1082
2
{
1083
2
    if (JSON_UNLIKELY(not j.is_boolean()))
1084
2
    {
1085
0
        JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name())));
1086
0
    }
1087
2
    b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
1088
2
}
1089
1090
template<typename BasicJsonType>
1091
void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
1092
11.4k
{
1093
11.4k
    if (JSON_UNLIKELY(not j.is_string()))
1094
11.4k
    {
1095
0
        JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
1096
0
    }
1097
11.4k
    s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
1098
11.4k
}
1099
1100
template <
1101
    typename BasicJsonType, typename CompatibleStringType,
1102
    enable_if_t <
1103
        is_compatible_string_type<BasicJsonType, CompatibleStringType>::value and
1104
        not std::is_same<typename BasicJsonType::string_t,
1105
                         CompatibleStringType>::value,
1106
        int > = 0 >
1107
void from_json(const BasicJsonType& j, CompatibleStringType& s)
1108
{
1109
    if (JSON_UNLIKELY(not j.is_string()))
1110
    {
1111
        JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
1112
    }
1113
1114
    s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
1115
}
1116
1117
template<typename BasicJsonType>
1118
void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
1119
148
{
1120
148
    get_arithmetic_value(j, val);
1121
148
}
1122
1123
template<typename BasicJsonType>
1124
void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
1125
{
1126
    get_arithmetic_value(j, val);
1127
}
1128
1129
template<typename BasicJsonType>
1130
void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
1131
{
1132
    get_arithmetic_value(j, val);
1133
}
1134
1135
template<typename BasicJsonType, typename EnumType,
1136
         enable_if_t<std::is_enum<EnumType>::value, int> = 0>
1137
void from_json(const BasicJsonType& j, EnumType& e)
1138
{
1139
    typename std::underlying_type<EnumType>::type val;
1140
    get_arithmetic_value(j, val);
1141
    e = static_cast<EnumType>(val);
1142
}
1143
1144
// forward_list doesn't have an insert method
1145
template<typename BasicJsonType, typename T, typename Allocator,
1146
         enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>
1147
void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
1148
{
1149
    if (JSON_UNLIKELY(not j.is_array()))
1150
    {
1151
        JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
1152
    }
1153
    std::transform(j.rbegin(), j.rend(),
1154
                   std::front_inserter(l), [](const BasicJsonType & i)
1155
    {
1156
        return i.template get<T>();
1157
    });
1158
}
1159
1160
// valarray doesn't have an insert method
1161
template<typename BasicJsonType, typename T,
1162
         enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>
1163
void from_json(const BasicJsonType& j, std::valarray<T>& l)
1164
{
1165
    if (JSON_UNLIKELY(not j.is_array()))
1166
    {
1167
        JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
1168
    }
1169
    l.resize(j.size());
1170
    std::copy(j.m_value.array->begin(), j.m_value.array->end(), std::begin(l));
1171
}
1172
1173
template<typename BasicJsonType>
1174
void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
1175
{
1176
    arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
1177
}
1178
1179
template <typename BasicJsonType, typename T, std::size_t N>
1180
auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
1181
                          priority_tag<2> /*unused*/)
1182
-> decltype(j.template get<T>(), void())
1183
{
1184
    for (std::size_t i = 0; i < N; ++i)
1185
    {
1186
        arr[i] = j.at(i).template get<T>();
1187
    }
1188
}
1189
1190
template<typename BasicJsonType, typename CompatibleArrayType>
1191
auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<1> /*unused*/)
1192
-> decltype(
1193
    arr.reserve(std::declval<typename CompatibleArrayType::size_type>()),
1194
    j.template get<typename CompatibleArrayType::value_type>(),
1195
    void())
1196
{
1197
    using std::end;
1198
1199
    arr.reserve(j.size());
1200
    std::transform(j.begin(), j.end(),
1201
                   std::inserter(arr, end(arr)), [](const BasicJsonType & i)
1202
    {
1203
        // get<BasicJsonType>() returns *this, this won't call a from_json
1204
        // method when value_type is BasicJsonType
1205
        return i.template get<typename CompatibleArrayType::value_type>();
1206
    });
1207
}
1208
1209
template <typename BasicJsonType, typename CompatibleArrayType>
1210
void from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr,
1211
                          priority_tag<0> /*unused*/)
1212
{
1213
    using std::end;
1214
1215
    std::transform(
1216
        j.begin(), j.end(), std::inserter(arr, end(arr)),
1217
        [](const BasicJsonType & i)
1218
    {
1219
        // get<BasicJsonType>() returns *this, this won't call a from_json
1220
        // method when value_type is BasicJsonType
1221
        return i.template get<typename CompatibleArrayType::value_type>();
1222
    });
1223
}
1224
1225
template <typename BasicJsonType, typename CompatibleArrayType,
1226
          enable_if_t <
1227
              is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value and
1228
              not is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value and
1229
              not is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value and
1230
              not is_basic_json<CompatibleArrayType>::value,
1231
              int > = 0 >
1232
1233
auto from_json(const BasicJsonType& j, CompatibleArrayType& arr)
1234
-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
1235
j.template get<typename CompatibleArrayType::value_type>(),
1236
void())
1237
{
1238
    if (JSON_UNLIKELY(not j.is_array()))
1239
    {
1240
        JSON_THROW(type_error::create(302, "type must be array, but is " +
1241
                                      std::string(j.type_name())));
1242
    }
1243
1244
    from_json_array_impl(j, arr, priority_tag<3> {});
1245
}
1246
1247
template<typename BasicJsonType, typename CompatibleObjectType,
1248
         enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value, int> = 0>
1249
void from_json(const BasicJsonType& j, CompatibleObjectType& obj)
1250
{
1251
    if (JSON_UNLIKELY(not j.is_object()))
1252
    {
1253
        JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name())));
1254
    }
1255
1256
    auto inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
1257
    using value_type = typename CompatibleObjectType::value_type;
1258
    std::transform(
1259
        inner_object->begin(), inner_object->end(),
1260
        std::inserter(obj, obj.begin()),
1261
        [](typename BasicJsonType::object_t::value_type const & p)
1262
    {
1263
        return value_type(p.first, p.second.template get<typename CompatibleObjectType::mapped_type>());
1264
    });
1265
}
1266
1267
// overload for arithmetic types, not chosen for basic_json template arguments
1268
// (BooleanType, etc..); note: Is it really necessary to provide explicit
1269
// overloads for boolean_t etc. in case of a custom BooleanType which is not
1270
// an arithmetic type?
1271
template<typename BasicJsonType, typename ArithmeticType,
1272
         enable_if_t <
1273
             std::is_arithmetic<ArithmeticType>::value and
1274
             not std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value and
1275
             not std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value and
1276
             not std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value and
1277
             not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
1278
             int> = 0>
1279
void from_json(const BasicJsonType& j, ArithmeticType& val)
1280
152
{
1281
152
    switch (static_cast<value_t>(j))
1282
152
    {
1283
152
        case value_t::number_unsigned:
1284
152
        {
1285
152
            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
1286
152
            break;
1287
152
        }
1288
152
        case value_t::number_integer:
1289
0
        {
1290
0
            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
1291
0
            break;
1292
152
        }
1293
152
        case value_t::number_float:
1294
0
        {
1295
0
            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
1296
0
            break;
1297
152
        }
1298
152
        case value_t::boolean:
1299
0
        {
1300
0
            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
1301
0
            break;
1302
152
        }
1303
152
1304
152
        default:
1305
0
            JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name())));
1306
152
    }
1307
152
}
1308
1309
template<typename BasicJsonType, typename A1, typename A2>
1310
void from_json(const BasicJsonType& j, std::pair<A1, A2>& p)
1311
{
1312
    p = {j.at(0).template get<A1>(), j.at(1).template get<A2>()};
1313
}
1314
1315
template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
1316
void from_json_tuple_impl(const BasicJsonType& j, Tuple& t, index_sequence<Idx...>)
1317
{
1318
    t = std::make_tuple(j.at(Idx).template get<typename std::tuple_element<Idx, Tuple>::type>()...);
1319
}
1320
1321
template<typename BasicJsonType, typename... Args>
1322
void from_json(const BasicJsonType& j, std::tuple<Args...>& t)
1323
{
1324
    from_json_tuple_impl(j, t, index_sequence_for<Args...> {});
1325
}
1326
1327
template <typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
1328
          typename = enable_if_t<not std::is_constructible<
1329
                                     typename BasicJsonType::string_t, Key>::value>>
1330
void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
1331
{
1332
    if (JSON_UNLIKELY(not j.is_array()))
1333
    {
1334
        JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
1335
    }
1336
    for (const auto& p : j)
1337
    {
1338
        if (JSON_UNLIKELY(not p.is_array()))
1339
        {
1340
            JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
1341
        }
1342
        m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
1343
    }
1344
}
1345
1346
template <typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
1347
          typename = enable_if_t<not std::is_constructible<
1348
                                     typename BasicJsonType::string_t, Key>::value>>
1349
void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
1350
{
1351
    if (JSON_UNLIKELY(not j.is_array()))
1352
    {
1353
        JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
1354
    }
1355
    for (const auto& p : j)
1356
    {
1357
        if (JSON_UNLIKELY(not p.is_array()))
1358
        {
1359
            JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
1360
        }
1361
        m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
1362
    }
1363
}
1364
1365
struct from_json_fn
1366
{
1367
    template<typename BasicJsonType, typename T>
1368
    auto operator()(const BasicJsonType& j, T& val) const
1369
    noexcept(noexcept(from_json(j, val)))
1370
    -> decltype(from_json(j, val), void())
1371
11.7k
    {
1372
11.7k
        return from_json(j, val);
1373
11.7k
    }
_ZNK8nlohmann6detail12from_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEbEEDTcmcl9from_jsonfp_fp0_Ecvv_EERKT_RT0_
Line
Count
Source
1371
2
    {
1372
2
        return from_json(j, val);
1373
2
    }
_ZNK8nlohmann6detail12from_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEESB_EEDTcmcl9from_jsonfp_fp0_Ecvv_EERKT_RT0_
Line
Count
Source
1371
11.4k
    {
1372
11.4k
        return from_json(j, val);
1373
11.4k
    }
_ZNK8nlohmann6detail12from_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEiEEDTcmcl9from_jsonfp_fp0_Ecvv_EERKT_RT0_
Line
Count
Source
1371
152
    {
1372
152
        return from_json(j, val);
1373
152
    }
_ZNK8nlohmann6detail12from_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEdEEDTcmcl9from_jsonfp_fp0_Ecvv_EERKT_RT0_
Line
Count
Source
1371
148
    {
1372
148
        return from_json(j, val);
1373
148
    }
1374
};
1375
}
1376
1377
/// namespace to hold default `from_json` function
1378
/// to see why this is required:
1379
/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
1380
namespace
1381
{
1382
constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::value;
1383
}
1384
}
1385
1386
// #include <nlohmann/detail/conversions/to_json.hpp>
1387
1388
1389
#include <ciso646> // or, and, not
1390
#include <iterator> // begin, end
1391
#include <tuple> // tuple, get
1392
#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
1393
#include <utility> // move, forward, declval, pair
1394
#include <valarray> // valarray
1395
#include <vector> // vector
1396
1397
// #include <nlohmann/detail/meta/cpp_future.hpp>
1398
1399
// #include <nlohmann/detail/meta/type_traits.hpp>
1400
1401
// #include <nlohmann/detail/value_t.hpp>
1402
1403
// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
1404
1405
1406
#include <cstddef> // size_t
1407
#include <string> // string, to_string
1408
#include <iterator> // input_iterator_tag
1409
1410
// #include <nlohmann/detail/value_t.hpp>
1411
1412
1413
namespace nlohmann
1414
{
1415
namespace detail
1416
{
1417
/// proxy class for the items() function
1418
template<typename IteratorType> class iteration_proxy
1419
{
1420
  private:
1421
    /// helper class for iteration
1422
    class iteration_proxy_internal
1423
    {
1424
      public:
1425
        using difference_type = std::ptrdiff_t;
1426
        using value_type = iteration_proxy_internal;
1427
        using pointer = iteration_proxy_internal*;
1428
        using reference = iteration_proxy_internal&;
1429
        using iterator_category = std::input_iterator_tag;
1430
1431
      private:
1432
        /// the iterator
1433
        IteratorType anchor;
1434
        /// an index for arrays (used to create key names)
1435
        std::size_t array_index = 0;
1436
        /// last stringified array index
1437
        mutable std::size_t array_index_last = 0;
1438
        /// a string representation of the array index
1439
        mutable std::string array_index_str = "0";
1440
        /// an empty string (to return a reference for primitive values)
1441
        const std::string empty_str = "";
1442
1443
      public:
1444
0
        explicit iteration_proxy_internal(IteratorType it) noexcept : anchor(it) {}
1445
1446
        iteration_proxy_internal(const iteration_proxy_internal&) = default;
1447
        iteration_proxy_internal& operator=(const iteration_proxy_internal&) = default;
1448
1449
        /// dereference operator (needed for range-based for)
1450
        iteration_proxy_internal& operator*()
1451
0
        {
1452
0
            return *this;
1453
0
        }
1454
1455
        /// increment operator (needed for range-based for)
1456
        iteration_proxy_internal& operator++()
1457
0
        {
1458
0
            ++anchor;
1459
0
            ++array_index;
1460
0
1461
0
            return *this;
1462
0
        }
1463
1464
        /// equality operator (needed for InputIterator)
1465
        bool operator==(const iteration_proxy_internal& o) const noexcept
1466
0
        {
1467
0
            return anchor == o.anchor;
1468
0
        }
1469
1470
        /// inequality operator (needed for range-based for)
1471
        bool operator!=(const iteration_proxy_internal& o) const noexcept
1472
0
        {
1473
0
            return anchor != o.anchor;
1474
0
        }
1475
1476
        /// return key of the iterator
1477
        const std::string& key() const
1478
0
        {
1479
0
            assert(anchor.m_object != nullptr);
1480
0
1481
0
            switch (anchor.m_object->type())
1482
0
            {
1483
0
                // use integer array index as key
1484
0
                case value_t::array:
1485
0
                {
1486
0
                    if (array_index != array_index_last)
1487
0
                    {
1488
0
                        array_index_str = std::to_string(array_index);
1489
0
                        array_index_last = array_index;
1490
0
                    }
1491
0
                    return array_index_str;
1492
0
                }
1493
0
1494
0
                // use key from the object
1495
0
                case value_t::object:
1496
0
                    return anchor.key();
1497
0
1498
0
                // use an empty key for all primitive types
1499
0
                default:
1500
0
                    return empty_str;
1501
0
            }
1502
0
        }
1503
1504
        /// return value of the iterator
1505
        typename IteratorType::reference value() const
1506
0
        {
1507
0
            return anchor.value();
1508
0
        }
1509
    };
1510
1511
    /// the container to iterate
1512
    typename IteratorType::reference container;
1513
1514
  public:
1515
    /// construct iteration proxy from a container
1516
    explicit iteration_proxy(typename IteratorType::reference cont) noexcept
1517
        : container(cont) {}
1518
1519
    /// return iterator begin (needed for range-based for)
1520
    iteration_proxy_internal begin() noexcept
1521
    {
1522
        return iteration_proxy_internal(container.begin());
1523
    }
1524
1525
    /// return iterator end (needed for range-based for)
1526
    iteration_proxy_internal end() noexcept
1527
    {
1528
        return iteration_proxy_internal(container.end());
1529
    }
1530
};
1531
}
1532
}
1533
1534
1535
namespace nlohmann
1536
{
1537
namespace detail
1538
{
1539
//////////////////
1540
// constructors //
1541
//////////////////
1542
1543
template<value_t> struct external_constructor;
1544
1545
template<>
1546
struct external_constructor<value_t::boolean>
1547
{
1548
    template<typename BasicJsonType>
1549
    static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
1550
603
    {
1551
603
        j.m_type = value_t::boolean;
1552
603
        j.m_value = b;
1553
603
        j.assert_invariant();
1554
603
    }
1555
};
1556
1557
template<>
1558
struct external_constructor<value_t::string>
1559
{
1560
    template<typename BasicJsonType>
1561
    static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
1562
62.5k
    {
1563
62.5k
        j.m_type = value_t::string;
1564
62.5k
        j.m_value = s;
1565
62.5k
        j.assert_invariant();
1566
62.5k
    }
1567
1568
    template<typename BasicJsonType>
1569
    static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
1570
423
    {
1571
423
        j.m_type = value_t::string;
1572
423
        j.m_value = std::move(s);
1573
423
        j.assert_invariant();
1574
423
    }
1575
1576
    template<typename BasicJsonType, typename CompatibleStringType,
1577
             enable_if_t<not std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
1578
                         int> = 0>
1579
    static void construct(BasicJsonType& j, const CompatibleStringType& str)
1580
210
    {
1581
210
        j.m_type = value_t::string;
1582
210
        j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
1583
210
        j.assert_invariant();
1584
210
    }
_ZN8nlohmann6detail20external_constructorILNS0_7value_tE3EE9constructINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEA474_cLi0EEEvRT_RKT0_
Line
Count
Source
1580
199
    {
1581
199
        j.m_type = value_t::string;
1582
199
        j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
1583
199
        j.assert_invariant();
1584
199
    }
_ZN8nlohmann6detail20external_constructorILNS0_7value_tE3EE9constructINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEPKcLi0EEEvRT_RKT0_
Line
Count
Source
1580
10
    {
1581
10
        j.m_type = value_t::string;
1582
10
        j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
1583
10
        j.assert_invariant();
1584
10
    }
_ZN8nlohmann6detail20external_constructorILNS0_7value_tE3EE9constructINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEA6_cLi0EEEvRT_RKT0_
Line
Count
Source
1580
1
    {
1581
1
        j.m_type = value_t::string;
1582
1
        j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
1583
1
        j.assert_invariant();
1584
1
    }
1585
};
1586
1587
template<>
1588
struct external_constructor<value_t::number_float>
1589
{
1590
    template<typename BasicJsonType>
1591
    static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
1592
57.4k
    {
1593
57.4k
        j.m_type = value_t::number_float;
1594
57.4k
        j.m_value = val;
1595
57.4k
        j.assert_invariant();
1596
57.4k
    }
1597
};
1598
1599
template<>
1600
struct external_constructor<value_t::number_unsigned>
1601
{
1602
    template<typename BasicJsonType>
1603
    static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
1604
77.1k
    {
1605
77.1k
        j.m_type = value_t::number_unsigned;
1606
77.1k
        j.m_value = val;
1607
77.1k
        j.assert_invariant();
1608
77.1k
    }
1609
};
1610
1611
template<>
1612
struct external_constructor<value_t::number_integer>
1613
{
1614
    template<typename BasicJsonType>
1615
    static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
1616
9.18k
    {
1617
9.18k
        j.m_type = value_t::number_integer;
1618
9.18k
        j.m_value = val;
1619
9.18k
        j.assert_invariant();
1620
9.18k
    }
1621
};
1622
1623
template<>
1624
struct external_constructor<value_t::array>
1625
{
1626
    template<typename BasicJsonType>
1627
    static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
1628
    {
1629
        j.m_type = value_t::array;
1630
        j.m_value = arr;
1631
        j.assert_invariant();
1632
    }
1633
1634
    template<typename BasicJsonType>
1635
    static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
1636
    {
1637
        j.m_type = value_t::array;
1638
        j.m_value = std::move(arr);
1639
        j.assert_invariant();
1640
    }
1641
1642
    template<typename BasicJsonType, typename CompatibleArrayType,
1643
             enable_if_t<not std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
1644
                         int> = 0>
1645
    static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
1646
    {
1647
        using std::begin;
1648
        using std::end;
1649
        j.m_type = value_t::array;
1650
        j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
1651
        j.assert_invariant();
1652
    }
1653
1654
    template<typename BasicJsonType>
1655
    static void construct(BasicJsonType& j, const std::vector<bool>& arr)
1656
    {
1657
        j.m_type = value_t::array;
1658
        j.m_value = value_t::array;
1659
        j.m_value.array->reserve(arr.size());
1660
        for (const bool x : arr)
1661
        {
1662
            j.m_value.array->push_back(x);
1663
        }
1664
        j.assert_invariant();
1665
    }
1666
1667
    template<typename BasicJsonType, typename T,
1668
             enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
1669
    static void construct(BasicJsonType& j, const std::valarray<T>& arr)
1670
    {
1671
        j.m_type = value_t::array;
1672
        j.m_value = value_t::array;
1673
        j.m_value.array->resize(arr.size());
1674
        std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin());
1675
        j.assert_invariant();
1676
    }
1677
};
1678
1679
template<>
1680
struct external_constructor<value_t::object>
1681
{
1682
    template<typename BasicJsonType>
1683
    static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
1684
    {
1685
        j.m_type = value_t::object;
1686
        j.m_value = obj;
1687
        j.assert_invariant();
1688
    }
1689
1690
    template<typename BasicJsonType>
1691
    static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
1692
    {
1693
        j.m_type = value_t::object;
1694
        j.m_value = std::move(obj);
1695
        j.assert_invariant();
1696
    }
1697
1698
    template<typename BasicJsonType, typename CompatibleObjectType,
1699
             enable_if_t<not std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int> = 0>
1700
    static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
1701
    {
1702
        using std::begin;
1703
        using std::end;
1704
1705
        j.m_type = value_t::object;
1706
        j.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
1707
        j.assert_invariant();
1708
    }
1709
};
1710
1711
/////////////
1712
// to_json //
1713
/////////////
1714
1715
template<typename BasicJsonType, typename T,
1716
         enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
1717
void to_json(BasicJsonType& j, T b) noexcept
1718
603
{
1719
603
    external_constructor<value_t::boolean>::construct(j, b);
1720
603
}
1721
1722
template<typename BasicJsonType, typename CompatibleString,
1723
         enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
1724
void to_json(BasicJsonType& j, const CompatibleString& s)
1725
62.7k
{
1726
62.7k
    external_constructor<value_t::string>::construct(j, s);
1727
62.7k
}
_ZN8nlohmann6detail7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEESA_Li0EEEvRT_RKT0_
Line
Count
Source
1725
62.5k
{
1726
62.5k
    external_constructor<value_t::string>::construct(j, s);
1727
62.5k
}
_ZN8nlohmann6detail7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEA474_cLi0EEEvRT_RKT0_
Line
Count
Source
1725
199
{
1726
199
    external_constructor<value_t::string>::construct(j, s);
1727
199
}
_ZN8nlohmann6detail7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEPKcLi0EEEvRT_RKT0_
Line
Count
Source
1725
10
{
1726
10
    external_constructor<value_t::string>::construct(j, s);
1727
10
}
_ZN8nlohmann6detail7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEA6_cLi0EEEvRT_RKT0_
Line
Count
Source
1725
1
{
1726
1
    external_constructor<value_t::string>::construct(j, s);
1727
1
}
1728
1729
template<typename BasicJsonType>
1730
void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
1731
423
{
1732
423
    external_constructor<value_t::string>::construct(j, std::move(s));
1733
423
}
1734
1735
template<typename BasicJsonType, typename FloatType,
1736
         enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
1737
void to_json(BasicJsonType& j, FloatType val) noexcept
1738
57.4k
{
1739
57.4k
    external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
1740
57.4k
}
1741
1742
template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
1743
         enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
1744
void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
1745
77.1k
{
1746
77.1k
    external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
1747
77.1k
}
_ZN8nlohmann6detail7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEmLi0EEEvRT_T0_
Line
Count
Source
1745
77.0k
{
1746
77.0k
    external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
1747
77.0k
}
_ZN8nlohmann6detail7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEjLi0EEEvRT_T0_
Line
Count
Source
1745
141
{
1746
141
    external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
1747
141
}
1748
1749
template<typename BasicJsonType, typename CompatibleNumberIntegerType,
1750
         enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
1751
void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
1752
9.18k
{
1753
9.18k
    external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
1754
9.18k
}
_ZN8nlohmann6detail7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEElLi0EEEvRT_T0_
Line
Count
Source
1752
9.18k
{
1753
9.18k
    external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
1754
9.18k
}
_ZN8nlohmann6detail7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEiLi0EEEvRT_T0_
Line
Count
Source
1752
1
{
1753
1
    external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
1754
1
}
1755
1756
template<typename BasicJsonType, typename EnumType,
1757
         enable_if_t<std::is_enum<EnumType>::value, int> = 0>
1758
void to_json(BasicJsonType& j, EnumType e) noexcept
1759
{
1760
    using underlying_type = typename std::underlying_type<EnumType>::type;
1761
    external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
1762
}
1763
1764
template<typename BasicJsonType>
1765
void to_json(BasicJsonType& j, const std::vector<bool>& e)
1766
{
1767
    external_constructor<value_t::array>::construct(j, e);
1768
}
1769
1770
template <typename BasicJsonType, typename CompatibleArrayType,
1771
          enable_if_t<is_compatible_array_type<BasicJsonType,
1772
                      CompatibleArrayType>::value and
1773
                      not is_compatible_object_type<
1774
                          BasicJsonType, CompatibleArrayType>::value and
1775
                      not is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value and
1776
                      not is_basic_json<CompatibleArrayType>::value,
1777
                      int> = 0>
1778
void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
1779
{
1780
    external_constructor<value_t::array>::construct(j, arr);
1781
}
1782
1783
template<typename BasicJsonType, typename T,
1784
         enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
1785
void to_json(BasicJsonType& j, const std::valarray<T>& arr)
1786
{
1787
    external_constructor<value_t::array>::construct(j, std::move(arr));
1788
}
1789
1790
template<typename BasicJsonType>
1791
void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
1792
{
1793
    external_constructor<value_t::array>::construct(j, std::move(arr));
1794
}
1795
1796
template<typename BasicJsonType, typename CompatibleObjectType,
1797
         enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value and not is_basic_json<CompatibleObjectType>::value, int> = 0>
1798
void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
1799
{
1800
    external_constructor<value_t::object>::construct(j, obj);
1801
}
1802
1803
template<typename BasicJsonType>
1804
void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
1805
{
1806
    external_constructor<value_t::object>::construct(j, std::move(obj));
1807
}
1808
1809
template <
1810
    typename BasicJsonType, typename T, std::size_t N,
1811
    enable_if_t<not std::is_constructible<typename BasicJsonType::string_t,
1812
                const T (&)[N]>::value,
1813
                int> = 0 >
1814
void to_json(BasicJsonType& j, const T (&arr)[N])
1815
{
1816
    external_constructor<value_t::array>::construct(j, arr);
1817
}
1818
1819
template<typename BasicJsonType, typename... Args>
1820
void to_json(BasicJsonType& j, const std::pair<Args...>& p)
1821
{
1822
    j = {p.first, p.second};
1823
}
1824
1825
// for https://github.com/nlohmann/json/pull/1134
1826
template<typename BasicJsonType, typename T,
1827
         enable_if_t<std::is_same<T, typename iteration_proxy<typename BasicJsonType::iterator>::iteration_proxy_internal>::value, int> = 0>
1828
void to_json(BasicJsonType& j, T b) noexcept
1829
{
1830
    j = {{b.key(), b.value()}};
1831
}
1832
1833
template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
1834
void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...>)
1835
{
1836
    j = {std::get<Idx>(t)...};
1837
}
1838
1839
template<typename BasicJsonType, typename... Args>
1840
void to_json(BasicJsonType& j, const std::tuple<Args...>& t)
1841
{
1842
    to_json_tuple_impl(j, t, index_sequence_for<Args...> {});
1843
}
1844
1845
struct to_json_fn
1846
{
1847
    template<typename BasicJsonType, typename T>
1848
    auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
1849
    -> decltype(to_json(j, std::forward<T>(val)), void())
1850
207k
    {
1851
207k
        return to_json(j, std::forward<T>(val));
1852
207k
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEERSB_EEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
Line
Count
Source
1850
62.5k
    {
1851
62.5k
        return to_json(j, std::forward<T>(val));
1852
62.5k
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEERbEEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
Line
Count
Source
1850
602
    {
1851
602
        return to_json(j, std::forward<T>(val));
1852
602
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEERmEEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
Line
Count
Source
1850
77.0k
    {
1851
77.0k
        return to_json(j, std::forward<T>(val));
1852
77.0k
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEERlEEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
Line
Count
Source
1850
9.18k
    {
1851
9.18k
        return to_json(j, std::forward<T>(val));
1852
9.18k
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEERdEEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
Line
Count
Source
1850
57.4k
    {
1851
57.4k
        return to_json(j, std::forward<T>(val));
1852
57.4k
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEERA474_KcEEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSH_
Line
Count
Source
1850
199
    {
1851
199
        return to_json(j, std::forward<T>(val));
1852
199
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEESB_EEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSE_
Line
Count
Source
1850
423
    {
1851
423
        return to_json(j, std::forward<T>(val));
1852
423
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEKSB_EEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
Line
Count
Source
1850
47
    {
1851
47
        return to_json(j, std::forward<T>(val));
1852
47
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEERjEEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
Line
Count
Source
1850
141
    {
1851
141
        return to_json(j, std::forward<T>(val));
1852
141
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEERKPKcEEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSI_
Line
Count
Source
1850
10
    {
1851
10
        return to_json(j, std::forward<T>(val));
1852
10
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEbEEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSE_
Line
Count
Source
1850
1
    {
1851
1
        return to_json(j, std::forward<T>(val));
1852
1
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEdEEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSE_
Line
Count
Source
1850
1
    {
1851
1
        return to_json(j, std::forward<T>(val));
1852
1
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEERA6_KcEEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSH_
Line
Count
Source
1850
1
    {
1851
1
        return to_json(j, std::forward<T>(val));
1852
1
    }
_ZNK8nlohmann6detail10to_json_fnclINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEiEEDTcmcl7to_jsonfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSE_
Line
Count
Source
1850
1
    {
1851
1
        return to_json(j, std::forward<T>(val));
1852
1
    }
1853
};
1854
}
1855
1856
/// namespace to hold default `to_json` function
1857
namespace
1858
{
1859
constexpr const auto& to_json = detail::static_const<detail::to_json_fn>::value;
1860
}
1861
}
1862
1863
// #include <nlohmann/detail/input/input_adapters.hpp>
1864
1865
1866
#include <cassert> // assert
1867
#include <cstddef> // size_t
1868
#include <cstring> // strlen
1869
#include <istream> // istream
1870
#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
1871
#include <memory> // shared_ptr, make_shared, addressof
1872
#include <numeric> // accumulate
1873
#include <string> // string, char_traits
1874
#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
1875
#include <utility> // pair, declval
1876
1877
// #include <nlohmann/detail/macro_scope.hpp>
1878
1879
1880
namespace nlohmann
1881
{
1882
namespace detail
1883
{
1884
/// the supported input formats
1885
enum class input_format_t { json, cbor, msgpack, ubjson };
1886
1887
////////////////////
1888
// input adapters //
1889
////////////////////
1890
1891
/*!
1892
@brief abstract input adapter interface
1893
1894
Produces a stream of std::char_traits<char>::int_type characters from a
1895
std::istream, a buffer, or some other input type. Accepts the return of
1896
exactly one non-EOF character for future input. The int_type characters
1897
returned consist of all valid char values as positive values (typically
1898
unsigned char), plus an EOF value outside that range, specified by the value
1899
of the function std::char_traits<char>::eof(). This value is typically -1, but
1900
could be any arbitrary value which is not a valid char value.
1901
*/
1902
struct input_adapter_protocol
1903
{
1904
    /// get a character [0,255] or std::char_traits<char>::eof().
1905
    virtual std::char_traits<char>::int_type get_character() = 0;
1906
835
    virtual ~input_adapter_protocol() = default;
1907
};
1908
1909
/// a type to simplify interfaces
1910
using input_adapter_t = std::shared_ptr<input_adapter_protocol>;
1911
1912
/*!
1913
Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at
1914
beginning of input. Does not support changing the underlying std::streambuf
1915
in mid-input. Maintains underlying std::istream and std::streambuf to support
1916
subsequent use of standard std::istream operations to process any input
1917
characters following those used in parsing the JSON input.  Clears the
1918
std::istream flags; any input errors (e.g., EOF) will be detected by the first
1919
subsequent call for input from the std::istream.
1920
*/
1921
class input_stream_adapter : public input_adapter_protocol
1922
{
1923
  public:
1924
    ~input_stream_adapter() override
1925
198
    {
1926
198
        // clear stream flags; we use underlying streambuf I/O, do not
1927
198
        // maintain ifstream flags
1928
198
        is.clear();
1929
198
    }
1930
1931
    explicit input_stream_adapter(std::istream& i)
1932
        : is(i), sb(*i.rdbuf())
1933
198
    {}
1934
1935
    // delete because of pointer members
1936
    input_stream_adapter(const input_stream_adapter&) = delete;
1937
    input_stream_adapter& operator=(input_stream_adapter&) = delete;
1938
1939
    // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
1940
    // ensure that std::char_traits<char>::eof() and the character 0xFF do not
1941
    // end up as the same value, eg. 0xFFFFFFFF.
1942
    std::char_traits<char>::int_type get_character() override
1943
451k
    {
1944
451k
        return sb.sbumpc();
1945
451k
    }
1946
1947
  private:
1948
    /// the associated input stream
1949
    std::istream& is;
1950
    std::streambuf& sb;
1951
};
1952
1953
/// input adapter for buffer input
1954
class input_buffer_adapter : public input_adapter_protocol
1955
{
1956
  public:
1957
    input_buffer_adapter(const char* b, const std::size_t l)
1958
        : cursor(b), limit(b + l)
1959
637
    {}
1960
1961
    // delete because of pointer members
1962
    input_buffer_adapter(const input_buffer_adapter&) = delete;
1963
    input_buffer_adapter& operator=(input_buffer_adapter&) = delete;
1964
1965
    std::char_traits<char>::int_type get_character() noexcept override
1966
4.12M
    {
1967
4.12M
        if (JSON_LIKELY(cursor < limit))
1968
4.12M
        {
1969
4.12M
            return std::char_traits<char>::to_int_type(*(cursor++));
1970
4.12M
        }
1971
4.12M
1972
4.12M
        return std::char_traits<char>::eof();
1973
4.12M
    }
1974
1975
  private:
1976
    /// pointer to the current character
1977
    const char* cursor;
1978
    /// pointer past the last character
1979
    const char* const limit;
1980
};
1981
1982
template<typename WideStringType>
1983
class wide_string_input_adapter : public input_adapter_protocol
1984
{
1985
  public:
1986
    explicit wide_string_input_adapter(const WideStringType& w) : str(w) {}
1987
1988
    std::char_traits<char>::int_type get_character() noexcept override
1989
0
    {
1990
0
        // check if buffer needs to be filled
1991
0
        if (utf8_bytes_index == utf8_bytes_filled)
1992
0
        {
1993
0
            if (sizeof(typename WideStringType::value_type) == 2)
1994
0
            {
1995
0
                fill_buffer_utf16();
1996
0
            }
1997
0
            else
1998
0
            {
1999
0
                fill_buffer_utf32();
2000
0
            }
2001
0
2002
0
            assert(utf8_bytes_filled > 0);
2003
0
            assert(utf8_bytes_index == 0);
2004
0
        }
2005
0
2006
0
        // use buffer
2007
0
        assert(utf8_bytes_filled > 0);
2008
0
        assert(utf8_bytes_index < utf8_bytes_filled);
2009
0
        return utf8_bytes[utf8_bytes_index++];
2010
0
    }
Unexecuted instantiation: _ZN8nlohmann6detail25wide_string_input_adapterINSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEEEE13get_characterEv
Unexecuted instantiation: _ZN8nlohmann6detail25wide_string_input_adapterINSt7__cxx1112basic_stringIDiSt11char_traitsIDiESaIDiEEEE13get_characterEv
Unexecuted instantiation: _ZN8nlohmann6detail25wide_string_input_adapterINSt7__cxx1112basic_stringIDsSt11char_traitsIDsESaIDsEEEE13get_characterEv
2011
2012
  private:
2013
    void fill_buffer_utf16()
2014
0
    {
2015
0
        utf8_bytes_index = 0;
2016
0
2017
0
        if (current_wchar == str.size())
2018
0
        {
2019
0
            utf8_bytes[0] = std::char_traits<char>::eof();
2020
0
            utf8_bytes_filled = 1;
2021
0
        }
2022
0
        else
2023
0
        {
2024
0
            // get the current character
2025
0
            const int wc = static_cast<int>(str[current_wchar++]);
2026
0
2027
0
            // UTF-16 to UTF-8 encoding
2028
0
            if (wc < 0x80)
2029
0
            {
2030
0
                utf8_bytes[0] = wc;
2031
0
                utf8_bytes_filled = 1;
2032
0
            }
2033
0
            else if (wc <= 0x7FF)
2034
0
            {
2035
0
                utf8_bytes[0] = 0xC0 | ((wc >> 6));
2036
0
                utf8_bytes[1] = 0x80 | (wc & 0x3F);
2037
0
                utf8_bytes_filled = 2;
2038
0
            }
2039
0
            else if (0xD800 > wc or wc >= 0xE000)
2040
0
            {
2041
0
                utf8_bytes[0] = 0xE0 | ((wc >> 12));
2042
0
                utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F);
2043
0
                utf8_bytes[2] = 0x80 | (wc & 0x3F);
2044
0
                utf8_bytes_filled = 3;
2045
0
            }
2046
0
            else
2047
0
            {
2048
0
                if (current_wchar < str.size())
2049
0
                {
2050
0
                    const int wc2 = static_cast<int>(str[current_wchar++]);
2051
0
                    const int charcode = 0x10000 + (((wc & 0x3FF) << 10) | (wc2 & 0x3FF));
2052
0
                    utf8_bytes[0] = 0xf0 | (charcode >> 18);
2053
0
                    utf8_bytes[1] = 0x80 | ((charcode >> 12) & 0x3F);
2054
0
                    utf8_bytes[2] = 0x80 | ((charcode >> 6) & 0x3F);
2055
0
                    utf8_bytes[3] = 0x80 | (charcode & 0x3F);
2056
0
                    utf8_bytes_filled = 4;
2057
0
                }
2058
0
                else
2059
0
                {
2060
0
                    // unknown character
2061
0
                    ++current_wchar;
2062
0
                    utf8_bytes[0] = wc;
2063
0
                    utf8_bytes_filled = 1;
2064
0
                }
2065
0
            }
2066
0
        }
2067
0
    }
Unexecuted instantiation: _ZN8nlohmann6detail25wide_string_input_adapterINSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEEEE17fill_buffer_utf16Ev
Unexecuted instantiation: _ZN8nlohmann6detail25wide_string_input_adapterINSt7__cxx1112basic_stringIDiSt11char_traitsIDiESaIDiEEEE17fill_buffer_utf16Ev
Unexecuted instantiation: _ZN8nlohmann6detail25wide_string_input_adapterINSt7__cxx1112basic_stringIDsSt11char_traitsIDsESaIDsEEEE17fill_buffer_utf16Ev
2068
2069
    void fill_buffer_utf32()
2070
0
    {
2071
0
        utf8_bytes_index = 0;
2072
0
2073
0
        if (current_wchar == str.size())
2074
0
        {
2075
0
            utf8_bytes[0] = std::char_traits<char>::eof();
2076
0
            utf8_bytes_filled = 1;
2077
0
        }
2078
0
        else
2079
0
        {
2080
0
            // get the current character
2081
0
            const int wc = static_cast<int>(str[current_wchar++]);
2082
0
2083
0
            // UTF-32 to UTF-8 encoding
2084
0
            if (wc < 0x80)
2085
0
            {
2086
0
                utf8_bytes[0] = wc;
2087
0
                utf8_bytes_filled = 1;
2088
0
            }
2089
0
            else if (wc <= 0x7FF)
2090
0
            {
2091
0
                utf8_bytes[0] = 0xC0 | ((wc >> 6) & 0x1F);
2092
0
                utf8_bytes[1] = 0x80 | (wc & 0x3F);
2093
0
                utf8_bytes_filled = 2;
2094
0
            }
2095
0
            else if (wc <= 0xFFFF)
2096
0
            {
2097
0
                utf8_bytes[0] = 0xE0 | ((wc >> 12) & 0x0F);
2098
0
                utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F);
2099
0
                utf8_bytes[2] = 0x80 | (wc & 0x3F);
2100
0
                utf8_bytes_filled = 3;
2101
0
            }
2102
0
            else if (wc <= 0x10FFFF)
2103
0
            {
2104
0
                utf8_bytes[0] = 0xF0 | ((wc >> 18 ) & 0x07);
2105
0
                utf8_bytes[1] = 0x80 | ((wc >> 12) & 0x3F);
2106
0
                utf8_bytes[2] = 0x80 | ((wc >> 6) & 0x3F);
2107
0
                utf8_bytes[3] = 0x80 | (wc & 0x3F);
2108
0
                utf8_bytes_filled = 4;
2109
0
            }
2110
0
            else
2111
0
            {
2112
0
                // unknown character
2113
0
                utf8_bytes[0] = wc;
2114
0
                utf8_bytes_filled = 1;
2115
0
            }
2116
0
        }
2117
0
    }
Unexecuted instantiation: _ZN8nlohmann6detail25wide_string_input_adapterINSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEEEE17fill_buffer_utf32Ev
Unexecuted instantiation: _ZN8nlohmann6detail25wide_string_input_adapterINSt7__cxx1112basic_stringIDiSt11char_traitsIDiESaIDiEEEE17fill_buffer_utf32Ev
Unexecuted instantiation: _ZN8nlohmann6detail25wide_string_input_adapterINSt7__cxx1112basic_stringIDsSt11char_traitsIDsESaIDsEEEE17fill_buffer_utf32Ev
2118
2119
  private:
2120
    /// the wstring to process
2121
    const WideStringType& str;
2122
2123
    /// index of the current wchar in str
2124
    std::size_t current_wchar = 0;
2125
2126
    /// a buffer for UTF-8 bytes
2127
    std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
2128
2129
    /// index to the utf8_codes array for the next valid byte
2130
    std::size_t utf8_bytes_index = 0;
2131
    /// number of valid bytes in the utf8_codes array
2132
    std::size_t utf8_bytes_filled = 0;
2133
};
2134
2135
class input_adapter
2136
{
2137
  public:
2138
    // native support
2139
2140
    /// input adapter for input stream
2141
    input_adapter(std::istream& i)
2142
198
        : ia(std::make_shared<input_stream_adapter>(i)) {}
2143
2144
    /// input adapter for input stream
2145
    input_adapter(std::istream&& i)
2146
0
        : ia(std::make_shared<input_stream_adapter>(i)) {}
2147
2148
    input_adapter(const std::wstring& ws)
2149
0
        : ia(std::make_shared<wide_string_input_adapter<std::wstring>>(ws)) {}
2150
2151
    input_adapter(const std::u16string& ws)
2152
0
        : ia(std::make_shared<wide_string_input_adapter<std::u16string>>(ws)) {}
2153
2154
    input_adapter(const std::u32string& ws)
2155
0
        : ia(std::make_shared<wide_string_input_adapter<std::u32string>>(ws)) {}
2156
2157
    /// input adapter for buffer
2158
    template<typename CharT,
2159
             typename std::enable_if<
2160
                 std::is_pointer<CharT>::value and
2161
                 std::is_integral<typename std::remove_pointer<CharT>::type>::value and
2162
                 sizeof(typename std::remove_pointer<CharT>::type) == 1,
2163
                 int>::type = 0>
2164
    input_adapter(CharT b, std::size_t l)
2165
        : ia(std::make_shared<input_buffer_adapter>(reinterpret_cast<const char*>(b), l)) {}
2166
2167
    // derived support
2168
2169
    /// input adapter for string literal
2170
    template<typename CharT,
2171
             typename std::enable_if<
2172
                 std::is_pointer<CharT>::value and
2173
                 std::is_integral<typename std::remove_pointer<CharT>::type>::value and
2174
                 sizeof(typename std::remove_pointer<CharT>::type) == 1,
2175
                 int>::type = 0>
2176
    input_adapter(CharT b)
2177
        : input_adapter(reinterpret_cast<const char*>(b),
2178
                        std::strlen(reinterpret_cast<const char*>(b))) {}
2179
2180
    /// input adapter for iterator range with contiguous storage
2181
    template<class IteratorType,
2182
             typename std::enable_if<
2183
                 std::is_same<typename std::iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
2184
                 int>::type = 0>
2185
    input_adapter(IteratorType first, IteratorType last)
2186
637
    {
2187
637
#ifndef NDEBUG
2188
637
        // assertion to check that the iterator range is indeed contiguous,
2189
637
        // see http://stackoverflow.com/a/35008842/266378 for more discussion
2190
637
        const auto is_contiguous = std::accumulate(
2191
637
                                       first, last, std::pair<bool, int>(true, 0),
2192
637
                                       [&first](std::pair<bool, int> res, decltype(*first) val)
2193
4.12M
        {
2194
4.12M
            res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
2195
4.12M
            return res;
2196
4.12M
        }).first;
_ZZN8nlohmann6detail13input_adapterC1IN9__gnu_cxx17__normal_iteratorIPKcNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEELi0EEET_SE_ENKUlSt4pairIbiERS5_E_clESG_SH_
Line
Count
Source
2193
12.5k
        {
2194
12.5k
            res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
2195
12.5k
            return res;
2196
12.5k
        }).first;
_ZZN8nlohmann6detail13input_adapterC1IPKcLi0EEET_S5_ENKUlSt4pairIbiERS3_E_clES7_S8_
Line
Count
Source
2193
4.11M
        {
2194
4.11M
            res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
2195
4.11M
            return res;
2196
4.11M
        }).first;
2197
637
        assert(is_contiguous);
2198
637
#endif
2199
637
2200
637
        // assertion to check that each element is 1 byte long
2201
637
        static_assert(
2202
637
            sizeof(typename std::iterator_traits<IteratorType>::value_type) == 1,
2203
637
            "each element in the iterator range must have the size of 1 byte");
2204
637
2205
637
        const auto len = static_cast<size_t>(std::distance(first, last));
2206
637
        if (JSON_LIKELY(len > 0))
2207
637
        {
2208
637
            // there is at least one element: use the address of first
2209
637
            ia = std::make_shared<input_buffer_adapter>(reinterpret_cast<const char*>(&(*first)), len);
2210
637
        }
2211
637
        else
2212
637
        {
2213
0
            // the address of first cannot be used: use nullptr
2214
0
            ia = std::make_shared<input_buffer_adapter>(nullptr, len);
2215
0
        }
2216
637
    }
_ZN8nlohmann6detail13input_adapterC2IN9__gnu_cxx17__normal_iteratorIPKcNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEELi0EEET_SE_
Line
Count
Source
2186
40
    {
2187
40
#ifndef NDEBUG
2188
40
        // assertion to check that the iterator range is indeed contiguous,
2189
40
        // see http://stackoverflow.com/a/35008842/266378 for more discussion
2190
40
        const auto is_contiguous = std::accumulate(
2191
40
                                       first, last, std::pair<bool, int>(true, 0),
2192
40
                                       [&first](std::pair<bool, int> res, decltype(*first) val)
2193
40
        {
2194
40
            res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
2195
40
            return res;
2196
40
        }).first;
2197
40
        assert(is_contiguous);
2198
40
#endif
2199
40
2200
40
        // assertion to check that each element is 1 byte long
2201
40
        static_assert(
2202
40
            sizeof(typename std::iterator_traits<IteratorType>::value_type) == 1,
2203
40
            "each element in the iterator range must have the size of 1 byte");
2204
40
2205
40
        const auto len = static_cast<size_t>(std::distance(first, last));
2206
40
        if (JSON_LIKELY(len > 0))
2207
40
        {
2208
40
            // there is at least one element: use the address of first
2209
40
            ia = std::make_shared<input_buffer_adapter>(reinterpret_cast<const char*>(&(*first)), len);
2210
40
        }
2211
40
        else
2212
40
        {
2213
0
            // the address of first cannot be used: use nullptr
2214
0
            ia = std::make_shared<input_buffer_adapter>(nullptr, len);
2215
0
        }
2216
40
    }
_ZN8nlohmann6detail13input_adapterC2IPKcLi0EEET_S5_
Line
Count
Source
2186
597
    {
2187
597
#ifndef NDEBUG
2188
597
        // assertion to check that the iterator range is indeed contiguous,
2189
597
        // see http://stackoverflow.com/a/35008842/266378 for more discussion
2190
597
        const auto is_contiguous = std::accumulate(
2191
597
                                       first, last, std::pair<bool, int>(true, 0),
2192
597
                                       [&first](std::pair<bool, int> res, decltype(*first) val)
2193
597
        {
2194
597
            res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
2195
597
            return res;
2196
597
        }).first;
2197
597
        assert(is_contiguous);
2198
597
#endif
2199
597
2200
597
        // assertion to check that each element is 1 byte long
2201
597
        static_assert(
2202
597
            sizeof(typename std::iterator_traits<IteratorType>::value_type) == 1,
2203
597
            "each element in the iterator range must have the size of 1 byte");
2204
597
2205
597
        const auto len = static_cast<size_t>(std::distance(first, last));
2206
597
        if (JSON_LIKELY(len > 0))
2207
597
        {
2208
597
            // there is at least one element: use the address of first
2209
597
            ia = std::make_shared<input_buffer_adapter>(reinterpret_cast<const char*>(&(*first)), len);
2210
597
        }
2211
597
        else
2212
597
        {
2213
0
            // the address of first cannot be used: use nullptr
2214
0
            ia = std::make_shared<input_buffer_adapter>(nullptr, len);
2215
0
        }
2216
597
    }
2217
2218
    /// input adapter for array
2219
    template<class T, std::size_t N>
2220
    input_adapter(T (&array)[N])
2221
597
        : input_adapter(std::begin(array), std::end(array)) {}
_ZN8nlohmann6detail13input_adapterC2IKcLm117EEERAT0__T_
Line
Count
Source
2221
199
        : input_adapter(std::begin(array), std::end(array)) {}
_ZN8nlohmann6detail13input_adapterC2IKcLm10282EEERAT0__T_
Line
Count
Source
2221
199
        : input_adapter(std::begin(array), std::end(array)) {}
_ZN8nlohmann6detail13input_adapterC2IKcLm10259EEERAT0__T_
Line
Count
Source
2221
199
        : input_adapter(std::begin(array), std::end(array)) {}
2222
2223
    /// input adapter for contiguous container
2224
    template<class ContiguousContainer, typename
2225
             std::enable_if<not std::is_pointer<ContiguousContainer>::value and
2226
                            std::is_base_of<std::random_access_iterator_tag, typename std::iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value,
2227
                            int>::type = 0>
2228
    input_adapter(const ContiguousContainer& c)
2229
40
        : input_adapter(std::begin(c), std::end(c)) {}
2230
2231
    operator input_adapter_t()
2232
835
    {
2233
835
        return ia;
2234
835
    }
2235
2236
  private:
2237
    /// the actual adapter
2238
    input_adapter_t ia = nullptr;
2239
};
2240
}
2241
}
2242
2243
// #include <nlohmann/detail/input/lexer.hpp>
2244
2245
2246
#include <clocale> // localeconv
2247
#include <cstddef> // size_t
2248
#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
2249
#include <cstdio> // snprintf
2250
#include <initializer_list> // initializer_list
2251
#include <string> // char_traits, string
2252
#include <vector> // vector
2253
2254
// #include <nlohmann/detail/macro_scope.hpp>
2255
2256
// #include <nlohmann/detail/input/input_adapters.hpp>
2257
2258
2259
namespace nlohmann
2260
{
2261
namespace detail
2262
{
2263
///////////
2264
// lexer //
2265
///////////
2266
2267
/*!
2268
@brief lexical analysis
2269
2270
This class organizes the lexical analysis during JSON deserialization.
2271
*/
2272
template<typename BasicJsonType>
2273
class lexer
2274
{
2275
    using number_integer_t = typename BasicJsonType::number_integer_t;
2276
    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
2277
    using number_float_t = typename BasicJsonType::number_float_t;
2278
    using string_t = typename BasicJsonType::string_t;
2279
2280
  public:
2281
    /// token types for the parser
2282
    enum class token_type
2283
    {
2284
        uninitialized,    ///< indicating the scanner is uninitialized
2285
        literal_true,     ///< the `true` literal
2286
        literal_false,    ///< the `false` literal
2287
        literal_null,     ///< the `null` literal
2288
        value_string,     ///< a string -- use get_string() for actual value
2289
        value_unsigned,   ///< an unsigned integer -- use get_number_unsigned() for actual value
2290
        value_integer,    ///< a signed integer -- use get_number_integer() for actual value
2291
        value_float,      ///< an floating point number -- use get_number_float() for actual value
2292
        begin_array,      ///< the character for array begin `[`
2293
        begin_object,     ///< the character for object begin `{`
2294
        end_array,        ///< the character for array end `]`
2295
        end_object,       ///< the character for object end `}`
2296
        name_separator,   ///< the name separator `:`
2297
        value_separator,  ///< the value separator `,`
2298
        parse_error,      ///< indicating a parse error
2299
        end_of_input,     ///< indicating the end of the input buffer
2300
        literal_or_value  ///< a literal or the begin of a value (only for diagnostics)
2301
    };
2302
2303
    /// return name of values of type token_type (only used for errors)
2304
    static const char* token_type_name(const token_type t) noexcept
2305
2
    {
2306
2
        switch (t)
2307
0
        {
2308
0
            case token_type::uninitialized:
2309
0
                return "<uninitialized>";
2310
0
            case token_type::literal_true:
2311
0
                return "true literal";
2312
0
            case token_type::literal_false:
2313
0
                return "false literal";
2314
0
            case token_type::literal_null:
2315
0
                return "null literal";
2316
0
            case token_type::value_string:
2317
0
                return "string literal";
2318
0
            case lexer::token_type::value_unsigned:
2319
0
            case lexer::token_type::value_integer:
2320
0
            case lexer::token_type::value_float:
2321
0
                return "number literal";
2322
0
            case token_type::begin_array:
2323
0
                return "'['";
2324
0
            case token_type::begin_object:
2325
0
                return "'{'";
2326
0
            case token_type::end_array:
2327
0
                return "']'";
2328
0
            case token_type::end_object:
2329
0
                return "'}'";
2330
0
            case token_type::name_separator:
2331
0
                return "':'";
2332
0
            case token_type::value_separator:
2333
0
                return "','";
2334
0
            case token_type::parse_error:
2335
0
                return "<parse error>";
2336
1
            case token_type::end_of_input:
2337
1
                return "end of input";
2338
1
            case token_type::literal_or_value:
2339
1
                return "'[', '{', or a literal";
2340
0
            // LCOV_EXCL_START
2341
0
            default: // catch non-enum values
2342
0
                return "unknown token";
2343
0
                // LCOV_EXCL_STOP
2344
0
        }
2345
2
    }
2346
2347
    explicit lexer(detail::input_adapter_t&& adapter)
2348
835
        : ia(std::move(adapter)), decimal_point_char(get_decimal_point()) {}
2349
2350
    // delete because of pointer members
2351
    lexer(const lexer&) = delete;
2352
    lexer& operator=(lexer&) = delete;
2353
2354
  private:
2355
    /////////////////////
2356
    // locales
2357
    /////////////////////
2358
2359
    /// return the locale-dependent decimal point
2360
    static char get_decimal_point() noexcept
2361
835
    {
2362
835
        const auto loc = localeconv();
2363
835
        assert(loc != nullptr);
2364
835
        return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
2365
835
    }
2366
2367
    /////////////////////
2368
    // scan functions
2369
    /////////////////////
2370
2371
    /*!
2372
    @brief get codepoint from 4 hex characters following `\u`
2373
2374
    For input "\u c1 c2 c3 c4" the codepoint is:
2375
      (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4
2376
    = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0)
2377
2378
    Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f'
2379
    must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The
2380
    conversion is done by subtracting the offset (0x30, 0x37, and 0x57)
2381
    between the ASCII value of the character and the desired integer value.
2382
2383
    @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or
2384
            non-hex character)
2385
    */
2386
    int get_codepoint()
2387
0
    {
2388
0
        // this function only makes sense after reading `\u`
2389
0
        assert(current == 'u');
2390
0
        int codepoint = 0;
2391
0
2392
0
        const auto factors = { 12, 8, 4, 0 };
2393
0
        for (const auto factor : factors)
2394
0
        {
2395
0
            get();
2396
0
2397
0
            if (current >= '0' and current <= '9')
2398
0
            {
2399
0
                codepoint += ((current - 0x30) << factor);
2400
0
            }
2401
0
            else if (current >= 'A' and current <= 'F')
2402
0
            {
2403
0
                codepoint += ((current - 0x37) << factor);
2404
0
            }
2405
0
            else if (current >= 'a' and current <= 'f')
2406
0
            {
2407
0
                codepoint += ((current - 0x57) << factor);
2408
0
            }
2409
0
            else
2410
0
            {
2411
0
                return -1;
2412
0
            }
2413
0
        }
2414
0
2415
0
        assert(0x0000 <= codepoint and codepoint <= 0xFFFF);
2416
0
        return codepoint;
2417
0
    }
2418
2419
    /*!
2420
    @brief check if the next byte(s) are inside a given range
2421
2422
    Adds the current byte and, for each passed range, reads a new byte and
2423
    checks if it is inside the range. If a violation was detected, set up an
2424
    error message and return false. Otherwise, return true.
2425
2426
    @param[in] ranges  list of integers; interpreted as list of pairs of
2427
                       inclusive lower and upper bound, respectively
2428
2429
    @pre The passed list @a ranges must have 2, 4, or 6 elements; that is,
2430
         1, 2, or 3 pairs. This precondition is enforced by an assertion.
2431
2432
    @return true if and only if no range violation was detected
2433
    */
2434
    bool next_byte_in_range(std::initializer_list<int> ranges)
2435
0
    {
2436
0
        assert(ranges.size() == 2 or ranges.size() == 4 or ranges.size() == 6);
2437
0
        add(current);
2438
0
2439
0
        for (auto range = ranges.begin(); range != ranges.end(); ++range)
2440
0
        {
2441
0
            get();
2442
0
            if (JSON_LIKELY(*range <= current and current <= *(++range)))
2443
0
            {
2444
0
                add(current);
2445
0
            }
2446
0
            else
2447
0
            {
2448
0
                error_message = "invalid string: ill-formed UTF-8 byte";
2449
0
                return false;
2450
0
            }
2451
0
        }
2452
0
2453
0
        return true;
2454
0
    }
2455
2456
    /*!
2457
    @brief scan a string literal
2458
2459
    This function scans a string according to Sect. 7 of RFC 7159. While
2460
    scanning, bytes are escaped and copied into buffer token_buffer. Then the
2461
    function returns successfully, token_buffer is *not* null-terminated (as it
2462
    may contain \0 bytes), and token_buffer.size() is the number of bytes in the
2463
    string.
2464
2465
    @return token_type::value_string if string could be successfully scanned,
2466
            token_type::parse_error otherwise
2467
2468
    @note In case of errors, variable error_message contains a textual
2469
          description.
2470
    */
2471
    token_type scan_string()
2472
309k
    {
2473
309k
        // reset token_buffer (ignore opening quote)
2474
309k
        reset();
2475
309k
2476
309k
        // we entered the function by reading an open quote
2477
309k
        assert(current == '\"');
2478
309k
2479
2.74M
        while (true)
2480
2.74M
        {
2481
2.74M
            // get next character
2482
2.74M
            switch (get())
2483
2.43M
            {
2484
2.43M
                // end of file while parsing string
2485
2.43M
                case std::char_traits<char>::eof():
2486
0
                {
2487
0
                    error_message = "invalid string: missing closing quote";
2488
0
                    return token_type::parse_error;
2489
0
                }
2490
0
2491
0
                // closing quote
2492
309k
                case '\"':
2493
309k
                {
2494
309k
                    return token_type::value_string;
2495
0
                }
2496
0
2497
0
                // escapes
2498
0
                case '\\':
2499
0
                {
2500
0
                    switch (get())
2501
0
                    {
2502
0
                        // quotation mark
2503
0
                        case '\"':
2504
0
                            add('\"');
2505
0
                            break;
2506
0
                        // reverse solidus
2507
0
                        case '\\':
2508
0
                            add('\\');
2509
0
                            break;
2510
0
                        // solidus
2511
0
                        case '/':
2512
0
                            add('/');
2513
0
                            break;
2514
0
                        // backspace
2515
0
                        case 'b':
2516
0
                            add('\b');
2517
0
                            break;
2518
0
                        // form feed
2519
0
                        case 'f':
2520
0
                            add('\f');
2521
0
                            break;
2522
0
                        // line feed
2523
0
                        case 'n':
2524
0
                            add('\n');
2525
0
                            break;
2526
0
                        // carriage return
2527
0
                        case 'r':
2528
0
                            add('\r');
2529
0
                            break;
2530
0
                        // tab
2531
0
                        case 't':
2532
0
                            add('\t');
2533
0
                            break;
2534
0
2535
0
                        // unicode escapes
2536
0
                        case 'u':
2537
0
                        {
2538
0
                            const int codepoint1 = get_codepoint();
2539
0
                            int codepoint = codepoint1; // start with codepoint1
2540
0
2541
0
                            if (JSON_UNLIKELY(codepoint1 == -1))
2542
0
                            {
2543
0
                                error_message = "invalid string: '\\u' must be followed by 4 hex digits";
2544
0
                                return token_type::parse_error;
2545
0
                            }
2546
0
2547
0
                            // check if code point is a high surrogate
2548
0
                            if (0xD800 <= codepoint1 and codepoint1 <= 0xDBFF)
2549
0
                            {
2550
0
                                // expect next \uxxxx entry
2551
0
                                if (JSON_LIKELY(get() == '\\' and get() == 'u'))
2552
0
                                {
2553
0
                                    const int codepoint2 = get_codepoint();
2554
0
2555
0
                                    if (JSON_UNLIKELY(codepoint2 == -1))
2556
0
                                    {
2557
0
                                        error_message = "invalid string: '\\u' must be followed by 4 hex digits";
2558
0
                                        return token_type::parse_error;
2559
0
                                    }
2560
0
2561
0
                                    // check if codepoint2 is a low surrogate
2562
0
                                    if (JSON_LIKELY(0xDC00 <= codepoint2 and codepoint2 <= 0xDFFF))
2563
0
                                    {
2564
0
                                        // overwrite codepoint
2565
0
                                        codepoint =
2566
0
                                            // high surrogate occupies the most significant 22 bits
2567
0
                                            (codepoint1 << 10)
2568
0
                                            // low surrogate occupies the least significant 15 bits
2569
0
                                            + codepoint2
2570
0
                                            // there is still the 0xD800, 0xDC00 and 0x10000 noise
2571
0
                                            // in the result so we have to subtract with:
2572
0
                                            // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
2573
0
                                            - 0x35FDC00;
2574
0
                                    }
2575
0
                                    else
2576
0
                                    {
2577
0
                                        error_message = "invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF";
2578
0
                                        return token_type::parse_error;
2579
0
                                    }
2580
0
                                }
2581
0
                                else
2582
0
                                {
2583
0
                                    error_message = "invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF";
2584
0
                                    return token_type::parse_error;
2585
0
                                }
2586
0
                            }
2587
0
                            else
2588
0
                            {
2589
0
                                if (JSON_UNLIKELY(0xDC00 <= codepoint1 and codepoint1 <= 0xDFFF))
2590
0
                                {
2591
0
                                    error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
2592
0
                                    return token_type::parse_error;
2593
0
                                }
2594
0
                            }
2595
0
2596
0
                            // result of the above calculation yields a proper codepoint
2597
0
                            assert(0x00 <= codepoint and codepoint <= 0x10FFFF);
2598
0
2599
0
                            // translate codepoint into bytes
2600
0
                            if (codepoint < 0x80)
2601
0
                            {
2602
0
                                // 1-byte characters: 0xxxxxxx (ASCII)
2603
0
                                add(codepoint);
2604
0
                            }
2605
0
                            else if (codepoint <= 0x7FF)
2606
0
                            {
2607
0
                                // 2-byte characters: 110xxxxx 10xxxxxx
2608
0
                                add(0xC0 | (codepoint >> 6));
2609
0
                                add(0x80 | (codepoint & 0x3F));
2610
0
                            }
2611
0
                            else if (codepoint <= 0xFFFF)
2612
0
                            {
2613
0
                                // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
2614
0
                                add(0xE0 | (codepoint >> 12));
2615
0
                                add(0x80 | ((codepoint >> 6) & 0x3F));
2616
0
                                add(0x80 | (codepoint & 0x3F));
2617
0
                            }
2618
0
                            else
2619
0
                            {
2620
0
                                // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
2621
0
                                add(0xF0 | (codepoint >> 18));
2622
0
                                add(0x80 | ((codepoint >> 12) & 0x3F));
2623
0
                                add(0x80 | ((codepoint >> 6) & 0x3F));
2624
0
                                add(0x80 | (codepoint & 0x3F));
2625
0
                            }
2626
0
2627
0
                            break;
2628
0
                        }
2629
0
2630
0
                        // other characters after escape
2631
0
                        default:
2632
0
                            error_message = "invalid string: forbidden character after backslash";
2633
0
                            return token_type::parse_error;
2634
0
                    }
2635
0
2636
0
                    break;
2637
0
                }
2638
0
2639
0
                // invalid control characters
2640
0
                case 0x00:
2641
0
                case 0x01:
2642
0
                case 0x02:
2643
0
                case 0x03:
2644
0
                case 0x04:
2645
0
                case 0x05:
2646
0
                case 0x06:
2647
0
                case 0x07:
2648
0
                case 0x08:
2649
0
                case 0x09:
2650
0
                case 0x0A:
2651
0
                case 0x0B:
2652
0
                case 0x0C:
2653
0
                case 0x0D:
2654
0
                case 0x0E:
2655
0
                case 0x0F:
2656
0
                case 0x10:
2657
0
                case 0x11:
2658
0
                case 0x12:
2659
0
                case 0x13:
2660
0
                case 0x14:
2661
0
                case 0x15:
2662
0
                case 0x16:
2663
0
                case 0x17:
2664
0
                case 0x18:
2665
0
                case 0x19:
2666
0
                case 0x1A:
2667
0
                case 0x1B:
2668
0
                case 0x1C:
2669
0
                case 0x1D:
2670
0
                case 0x1E:
2671
0
                case 0x1F:
2672
0
                {
2673
0
                    error_message = "invalid string: control character must be escaped";
2674
0
                    return token_type::parse_error;
2675
0
                }
2676
0
2677
0
                // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
2678
2.43M
                case 0x20:
2679
2.43M
                case 0x21:
2680
2.43M
                case 0x23:
2681
2.43M
                case 0x24:
2682
2.43M
                case 0x25:
2683
2.43M
                case 0x26:
2684
2.43M
                case 0x27:
2685
2.43M
                case 0x28:
2686
2.43M
                case 0x29:
2687
2.43M
                case 0x2A:
2688
2.43M
                case 0x2B:
2689
2.43M
                case 0x2C:
2690
2.43M
                case 0x2D:
2691
2.43M
                case 0x2E:
2692
2.43M
                case 0x2F:
2693
2.43M
                case 0x30:
2694
2.43M
                case 0x31:
2695
2.43M
                case 0x32:
2696
2.43M
                case 0x33:
2697
2.43M
                case 0x34:
2698
2.43M
                case 0x35:
2699
2.43M
                case 0x36:
2700
2.43M
                case 0x37:
2701
2.43M
                case 0x38:
2702
2.43M
                case 0x39:
2703
2.43M
                case 0x3A:
2704
2.43M
                case 0x3B:
2705
2.43M
                case 0x3C:
2706
2.43M
                case 0x3D:
2707
2.43M
                case 0x3E:
2708
2.43M
                case 0x3F:
2709
2.43M
                case 0x40:
2710
2.43M
                case 0x41:
2711
2.43M
                case 0x42:
2712
2.43M
                case 0x43:
2713
2.43M
                case 0x44:
2714
2.43M
                case 0x45:
2715
2.43M
                case 0x46:
2716
2.43M
                case 0x47:
2717
2.43M
                case 0x48:
2718
2.43M
                case 0x49:
2719
2.43M
                case 0x4A:
2720
2.43M
                case 0x4B:
2721
2.43M
                case 0x4C:
2722
2.43M
                case 0x4D:
2723
2.43M
                case 0x4E:
2724
2.43M
                case 0x4F:
2725
2.43M
                case 0x50:
2726
2.43M
                case 0x51:
2727
2.43M
                case 0x52:
2728
2.43M
                case 0x53:
2729
2.43M
                case 0x54:
2730
2.43M
                case 0x55:
2731
2.43M
                case 0x56:
2732
2.43M
                case 0x57:
2733
2.43M
                case 0x58:
2734
2.43M
                case 0x59:
2735
2.43M
                case 0x5A:
2736
2.43M
                case 0x5B:
2737
2.43M
                case 0x5D:
2738
2.43M
                case 0x5E:
2739
2.43M
                case 0x5F:
2740
2.43M
                case 0x60:
2741
2.43M
                case 0x61:
2742
2.43M
                case 0x62:
2743
2.43M
                case 0x63:
2744
2.43M
                case 0x64:
2745
2.43M
                case 0x65:
2746
2.43M
                case 0x66:
2747
2.43M
                case 0x67:
2748
2.43M
                case 0x68:
2749
2.43M
                case 0x69:
2750
2.43M
                case 0x6A:
2751
2.43M
                case 0x6B:
2752
2.43M
                case 0x6C:
2753
2.43M
                case 0x6D:
2754
2.43M
                case 0x6E:
2755
2.43M
                case 0x6F:
2756
2.43M
                case 0x70:
2757
2.43M
                case 0x71:
2758
2.43M
                case 0x72:
2759
2.43M
                case 0x73:
2760
2.43M
                case 0x74:
2761
2.43M
                case 0x75:
2762
2.43M
                case 0x76:
2763
2.43M
                case 0x77:
2764
2.43M
                case 0x78:
2765
2.43M
                case 0x79:
2766
2.43M
                case 0x7A:
2767
2.43M
                case 0x7B:
2768
2.43M
                case 0x7C:
2769
2.43M
                case 0x7D:
2770
2.43M
                case 0x7E:
2771
2.43M
                case 0x7F:
2772
2.43M
                {
2773
2.43M
                    add(current);
2774
2.43M
                    break;
2775
2.43M
                }
2776
2.43M
2777
2.43M
                // U+0080..U+07FF: bytes C2..DF 80..BF
2778
2.43M
                case 0xC2:
2779
0
                case 0xC3:
2780
0
                case 0xC4:
2781
0
                case 0xC5:
2782
0
                case 0xC6:
2783
0
                case 0xC7:
2784
0
                case 0xC8:
2785
0
                case 0xC9:
2786
0
                case 0xCA:
2787
0
                case 0xCB:
2788
0
                case 0xCC:
2789
0
                case 0xCD:
2790
0
                case 0xCE:
2791
0
                case 0xCF:
2792
0
                case 0xD0:
2793
0
                case 0xD1:
2794
0
                case 0xD2:
2795
0
                case 0xD3:
2796
0
                case 0xD4:
2797
0
                case 0xD5:
2798
0
                case 0xD6:
2799
0
                case 0xD7:
2800
0
                case 0xD8:
2801
0
                case 0xD9:
2802
0
                case 0xDA:
2803
0
                case 0xDB:
2804
0
                case 0xDC:
2805
0
                case 0xDD:
2806
0
                case 0xDE:
2807
0
                case 0xDF:
2808
0
                {
2809
0
                    if (JSON_UNLIKELY(not next_byte_in_range({0x80, 0xBF})))
2810
0
                    {
2811
0
                        return token_type::parse_error;
2812
0
                    }
2813
0
                    break;
2814
0
                }
2815
0
2816
0
                // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
2817
0
                case 0xE0:
2818
0
                {
2819
0
                    if (JSON_UNLIKELY(not (next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
2820
0
                    {
2821
0
                        return token_type::parse_error;
2822
0
                    }
2823
0
                    break;
2824
0
                }
2825
0
2826
0
                // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
2827
0
                // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
2828
0
                case 0xE1:
2829
0
                case 0xE2:
2830
0
                case 0xE3:
2831
0
                case 0xE4:
2832
0
                case 0xE5:
2833
0
                case 0xE6:
2834
0
                case 0xE7:
2835
0
                case 0xE8:
2836
0
                case 0xE9:
2837
0
                case 0xEA:
2838
0
                case 0xEB:
2839
0
                case 0xEC:
2840
0
                case 0xEE:
2841
0
                case 0xEF:
2842
0
                {
2843
0
                    if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
2844
0
                    {
2845
0
                        return token_type::parse_error;
2846
0
                    }
2847
0
                    break;
2848
0
                }
2849
0
2850
0
                // U+D000..U+D7FF: bytes ED 80..9F 80..BF
2851
0
                case 0xED:
2852
0
                {
2853
0
                    if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
2854
0
                    {
2855
0
                        return token_type::parse_error;
2856
0
                    }
2857
0
                    break;
2858
0
                }
2859
0
2860
0
                // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
2861
0
                case 0xF0:
2862
0
                {
2863
0
                    if (JSON_UNLIKELY(not (next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
2864
0
                    {
2865
0
                        return token_type::parse_error;
2866
0
                    }
2867
0
                    break;
2868
0
                }
2869
0
2870
0
                // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
2871
0
                case 0xF1:
2872
0
                case 0xF2:
2873
0
                case 0xF3:
2874
0
                {
2875
0
                    if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
2876
0
                    {
2877
0
                        return token_type::parse_error;
2878
0
                    }
2879
0
                    break;
2880
0
                }
2881
0
2882
0
                // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
2883
0
                case 0xF4:
2884
0
                {
2885
0
                    if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
2886
0
                    {
2887
0
                        return token_type::parse_error;
2888
0
                    }
2889
0
                    break;
2890
0
                }
2891
0
2892
0
                // remaining bytes (80..C1 and F5..FF) are ill-formed
2893
0
                default:
2894
0
                {
2895
0
                    error_message = "invalid string: ill-formed UTF-8 byte";
2896
0
                    return token_type::parse_error;
2897
0
                }
2898
2.43M
            }
2899
2.74M
        }
2900
309k
    }
2901
2902
    static void strtof(float& f, const char* str, char** endptr) noexcept
2903
    {
2904
        f = std::strtof(str, endptr);
2905
    }
2906
2907
    static void strtof(double& f, const char* str, char** endptr) noexcept
2908
57.4k
    {
2909
57.4k
        f = std::strtod(str, endptr);
2910
57.4k
    }
2911
2912
    static void strtof(long double& f, const char* str, char** endptr) noexcept
2913
    {
2914
        f = std::strtold(str, endptr);
2915
    }
2916
2917
    /*!
2918
    @brief scan a number literal
2919
2920
    This function scans a string according to Sect. 6 of RFC 7159.
2921
2922
    The function is realized with a deterministic finite state machine derived
2923
    from the grammar described in RFC 7159. Starting in state "init", the
2924
    input is read and used to determined the next state. Only state "done"
2925
    accepts the number. State "error" is a trap state to model errors. In the
2926
    table below, "anything" means any character but the ones listed before.
2927
2928
    state    | 0        | 1-9      | e E      | +       | -       | .        | anything
2929
    ---------|----------|----------|----------|---------|---------|----------|-----------
2930
    init     | zero     | any1     | [error]  | [error] | minus   | [error]  | [error]
2931
    minus    | zero     | any1     | [error]  | [error] | [error] | [error]  | [error]
2932
    zero     | done     | done     | exponent | done    | done    | decimal1 | done
2933
    any1     | any1     | any1     | exponent | done    | done    | decimal1 | done
2934
    decimal1 | decimal2 | [error]  | [error]  | [error] | [error] | [error]  | [error]
2935
    decimal2 | decimal2 | decimal2 | exponent | done    | done    | done     | done
2936
    exponent | any2     | any2     | [error]  | sign    | sign    | [error]  | [error]
2937
    sign     | any2     | any2     | [error]  | [error] | [error] | [error]  | [error]
2938
    any2     | any2     | any2     | done     | done    | done    | done     | done
2939
2940
    The state machine is realized with one label per state (prefixed with
2941
    "scan_number_") and `goto` statements between them. The state machine
2942
    contains cycles, but any cycle can be left when EOF is read. Therefore,
2943
    the function is guaranteed to terminate.
2944
2945
    During scanning, the read bytes are stored in token_buffer. This string is
2946
    then converted to a signed integer, an unsigned integer, or a
2947
    floating-point number.
2948
2949
    @return token_type::value_unsigned, token_type::value_integer, or
2950
            token_type::value_float if number could be successfully scanned,
2951
            token_type::parse_error otherwise
2952
2953
    @note The scanner is independent of the current locale. Internally, the
2954
          locale's decimal point is used instead of `.` to work with the
2955
          locale-dependent converters.
2956
    */
2957
    token_type scan_number()
2958
143k
    {
2959
143k
        // reset token_buffer to store the number's bytes
2960
143k
        reset();
2961
143k
2962
143k
        // the type of the parsed number; initially set to unsigned; will be
2963
143k
        // changed if minus sign, decimal point or exponent is read
2964
143k
        token_type number_type = token_type::value_unsigned;
2965
143k
2966
143k
        // state (init): we just found out we need to scan a number
2967
143k
        switch (current)
2968
0
        {
2969
9.18k
            case '-':
2970
9.18k
            {
2971
9.18k
                add(current);
2972
9.18k
                goto scan_number_minus;
2973
9.18k
            }
2974
9.18k
2975
19.3k
            case '0':
2976
19.3k
            {
2977
19.3k
                add(current);
2978
19.3k
                goto scan_number_zero;
2979
9.18k
            }
2980
9.18k
2981
115k
            case '1':
2982
115k
            case '2':
2983
115k
            case '3':
2984
115k
            case '4':
2985
115k
            case '5':
2986
115k
            case '6':
2987
115k
            case '7':
2988
115k
            case '8':
2989
115k
            case '9':
2990
115k
            {
2991
115k
                add(current);
2992
115k
                goto scan_number_any1;
2993
115k
            }
2994
115k
2995
115k
            // LCOV_EXCL_START
2996
115k
            default:
2997
0
            {
2998
0
                // all other characters are rejected outside scan_number()
2999
0
                assert(false);
3000
0
            }
3001
0
                // LCOV_EXCL_STOP
3002
0
        }
3003
143k
3004
143k
scan_number_minus:
3005
9.18k
        // state: we just parsed a leading minus sign
3006
9.18k
        number_type = token_type::value_integer;
3007
9.18k
        switch (get())
3008
0
        {
3009
0
            case '0':
3010
0
            {
3011
0
                add(current);
3012
0
                goto scan_number_zero;
3013
0
            }
3014
0
3015
9.18k
            case '1':
3016
9.18k
            case '2':
3017
9.18k
            case '3':
3018
9.18k
            case '4':
3019
9.18k
            case '5':
3020
9.18k
            case '6':
3021
9.18k
            case '7':
3022
9.18k
            case '8':
3023
9.18k
            case '9':
3024
9.18k
            {
3025
9.18k
                add(current);
3026
9.18k
                goto scan_number_any1;
3027
9.18k
            }
3028
9.18k
3029
9.18k
            default:
3030
0
            {
3031
0
                error_message = "invalid number; expected digit after '-'";
3032
0
                return token_type::parse_error;
3033
9.18k
            }
3034
0
        }
3035
9.18k
3036
19.3k
scan_number_zero:
3037
19.3k
        // state: we just parse a zero (maybe with a leading minus sign)
3038
19.3k
        switch (get())
3039
0
        {
3040
199
            case '.':
3041
199
            {
3042
199
                add(decimal_point_char);
3043
199
                goto scan_number_decimal1;
3044
199
            }
3045
199
3046
199
            case 'e':
3047
0
            case 'E':
3048
0
            {
3049
0
                add(current);
3050
0
                goto scan_number_exponent;
3051
0
            }
3052
0
3053
19.1k
            default:
3054
19.1k
                goto scan_number_done;
3055
0
        }
3056
19.3k
3057
423k
scan_number_any1:
3058
423k
        // state: we just parsed a number 0-9 (maybe with a leading minus sign)
3059
423k
        switch (get())
3060
0
        {
3061
299k
            case '0':
3062
299k
            case '1':
3063
299k
            case '2':
3064
299k
            case '3':
3065
299k
            case '4':
3066
299k
            case '5':
3067
299k
            case '6':
3068
299k
            case '7':
3069
299k
            case '8':
3070
299k
            case '9':
3071
299k
            {
3072
299k
                add(current);
3073
299k
                goto scan_number_any1;
3074
299k
            }
3075
299k
3076
299k
            case '.':
3077
57.2k
            {
3078
57.2k
                add(decimal_point_char);
3079
57.2k
                goto scan_number_decimal1;
3080
299k
            }
3081
299k
3082
299k
            case 'e':
3083
0
            case 'E':
3084
0
            {
3085
0
                add(current);
3086
0
                goto scan_number_exponent;
3087
0
            }
3088
0
3089
67.0k
            default:
3090
67.0k
                goto scan_number_done;
3091
0
        }
3092
423k
3093
423k
scan_number_decimal1:
3094
57.4k
        // state: we just parsed a decimal point
3095
57.4k
        number_type = token_type::value_float;
3096
57.4k
        switch (get())
3097
0
        {
3098
57.4k
            case '0':
3099
57.4k
            case '1':
3100
57.4k
            case '2':
3101
57.4k
            case '3':
3102
57.4k
            case '4':
3103
57.4k
            case '5':
3104
57.4k
            case '6':
3105
57.4k
            case '7':
3106
57.4k
            case '8':
3107
57.4k
            case '9':
3108
57.4k
            {
3109
57.4k
                add(current);
3110
57.4k
                goto scan_number_decimal2;
3111
57.4k
            }
3112
57.4k
3113
57.4k
            default:
3114
0
            {
3115
0
                error_message = "invalid number; expected digit after '.'";
3116
0
                return token_type::parse_error;
3117
57.4k
            }
3118
0
        }
3119
57.4k
3120
245k
scan_number_decimal2:
3121
245k
        // we just parsed at least one number after a decimal point
3122
245k
        switch (get())
3123
0
        {
3124
188k
            case '0':
3125
188k
            case '1':
3126
188k
            case '2':
3127
188k
            case '3':
3128
188k
            case '4':
3129
188k
            case '5':
3130
188k
            case '6':
3131
188k
            case '7':
3132
188k
            case '8':
3133
188k
            case '9':
3134
188k
            {
3135
188k
                add(current);
3136
188k
                goto scan_number_decimal2;
3137
188k
            }
3138
188k
3139
188k
            case 'e':
3140
0
            case 'E':
3141
0
            {
3142
0
                add(current);
3143
0
                goto scan_number_exponent;
3144
0
            }
3145
0
3146
57.4k
            default:
3147
57.4k
                goto scan_number_done;
3148
0
        }
3149
245k
3150
245k
scan_number_exponent:
3151
0
        // we just parsed an exponent
3152
0
        number_type = token_type::value_float;
3153
0
        switch (get())
3154
0
        {
3155
0
            case '+':
3156
0
            case '-':
3157
0
            {
3158
0
                add(current);
3159
0
                goto scan_number_sign;
3160
0
            }
3161
0
3162
0
            case '0':
3163
0
            case '1':
3164
0
            case '2':
3165
0
            case '3':
3166
0
            case '4':
3167
0
            case '5':
3168
0
            case '6':
3169
0
            case '7':
3170
0
            case '8':
3171
0
            case '9':
3172
0
            {
3173
0
                add(current);
3174
0
                goto scan_number_any2;
3175
0
            }
3176
0
3177
0
            default:
3178
0
            {
3179
0
                error_message =
3180
0
                    "invalid number; expected '+', '-', or digit after exponent";
3181
0
                return token_type::parse_error;
3182
0
            }
3183
0
        }
3184
0
3185
0
scan_number_sign:
3186
0
        // we just parsed an exponent sign
3187
0
        switch (get())
3188
0
        {
3189
0
            case '0':
3190
0
            case '1':
3191
0
            case '2':
3192
0
            case '3':
3193
0
            case '4':
3194
0
            case '5':
3195
0
            case '6':
3196
0
            case '7':
3197
0
            case '8':
3198
0
            case '9':
3199
0
            {
3200
0
                add(current);
3201
0
                goto scan_number_any2;
3202
0
            }
3203
0
3204
0
            default:
3205
0
            {
3206
0
                error_message = "invalid number; expected digit after exponent sign";
3207
0
                return token_type::parse_error;
3208
0
            }
3209
0
        }
3210
0
3211
0
scan_number_any2:
3212
0
        // we just parsed a number after the exponent or exponent sign
3213
0
        switch (get())
3214
0
        {
3215
0
            case '0':
3216
0
            case '1':
3217
0
            case '2':
3218
0
            case '3':
3219
0
            case '4':
3220
0
            case '5':
3221
0
            case '6':
3222
0
            case '7':
3223
0
            case '8':
3224
0
            case '9':
3225
0
            {
3226
0
                add(current);
3227
0
                goto scan_number_any2;
3228
0
            }
3229
0
3230
0
            default:
3231
0
                goto scan_number_done;
3232
0
        }
3233
0
3234
143k
scan_number_done:
3235
143k
        // unget the character after the number (we only read it to know that
3236
143k
        // we are done scanning a number)
3237
143k
        unget();
3238
143k
3239
143k
        char* endptr = nullptr;
3240
143k
        errno = 0;
3241
143k
3242
143k
        // try to parse integers first and fall back to floats
3243
143k
        if (number_type == token_type::value_unsigned)
3244
143k
        {
3245
77.0k
            const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
3246
77.0k
3247
77.0k
            // we checked the number format before
3248
77.0k
            assert(endptr == token_buffer.data() + token_buffer.size());
3249
77.0k
3250
77.0k
            if (errno == 0)
3251
77.0k
            {
3252
77.0k
                value_unsigned = static_cast<number_unsigned_t>(x);
3253
77.0k
                if (value_unsigned == x)
3254
77.0k
                {
3255
77.0k
                    return token_type::value_unsigned;
3256
77.0k
                }
3257
77.0k
            }
3258
77.0k
        }
3259
143k
        else if (number_type == token_type::value_integer)
3260
66.6k
        {
3261
9.18k
            const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
3262
9.18k
3263
9.18k
            // we checked the number format before
3264
9.18k
            assert(endptr == token_buffer.data() + token_buffer.size());
3265
9.18k
3266
9.18k
            if (errno == 0)
3267
9.18k
            {
3268
9.18k
                value_integer = static_cast<number_integer_t>(x);
3269
9.18k
                if (value_integer == x)
3270
9.18k
                {
3271
9.18k
                    return token_type::value_integer;
3272
9.18k
                }
3273
9.18k
            }
3274
9.18k
        }
3275
143k
3276
143k
        // this code is reached if we parse a floating-point number or if an
3277
143k
        // integer conversion above failed
3278
143k
        strtof(value_float, token_buffer.data(), &endptr);
3279
57.4k
3280
57.4k
        // we checked the number format before
3281
57.4k
        assert(endptr == token_buffer.data() + token_buffer.size());
3282
57.4k
3283
57.4k
        return token_type::value_float;
3284
143k
    }
3285
3286
    /*!
3287
    @param[in] literal_text  the literal text to expect
3288
    @param[in] length        the length of the passed literal text
3289
    @param[in] return_type   the token type to return on success
3290
    */
3291
    token_type scan_literal(const char* literal_text, const std::size_t length,
3292
                            token_type return_type)
3293
1.00k
    {
3294
1.00k
        assert(current == literal_text[0]);
3295
4.01k
        for (std::size_t i = 1; i < length; ++i)
3296
3.01k
        {
3297
3.01k
            if (JSON_UNLIKELY(get() != literal_text[i]))
3298
3.01k
            {
3299
0
                error_message = "invalid literal";
3300
0
                return token_type::parse_error;
3301
0
            }
3302
3.01k
        }
3303
1.00k
        return return_type;
3304
1.00k
    }
3305
3306
    /////////////////////
3307
    // input management
3308
    /////////////////////
3309
3310
    /// reset token_buffer; current character is beginning of token
3311
    void reset() noexcept
3312
453k
    {
3313
453k
        token_buffer.clear();
3314
453k
        token_string.clear();
3315
453k
        token_string.push_back(std::char_traits<char>::to_char_type(current));
3316
453k
    }
3317
3318
    /*
3319
    @brief get next character from the input
3320
3321
    This function provides the interface to the used input adapter. It does
3322
    not throw in case the input reached EOF, but returns a
3323
    `std::char_traits<char>::eof()` in that case.  Stores the scanned characters
3324
    for use in error messages.
3325
3326
    @return character read from the input
3327
    */
3328
    std::char_traits<char>::int_type get()
3329
4.71M
    {
3330
4.71M
        ++chars_read;
3331
4.71M
        if (next_unget)
3332
4.71M
        {
3333
144k
            // just reset the next_unget variable and work with current
3334
144k
            next_unget = false;
3335
144k
        }
3336
4.71M
        else
3337
4.71M
        {
3338
4.57M
            current = ia->get_character();
3339
4.57M
        }
3340
4.71M
3341
4.71M
        if (JSON_LIKELY(current != std::char_traits<char>::eof()))
3342
4.71M
        {
3343
4.71M
            token_string.push_back(std::char_traits<char>::to_char_type(current));
3344
4.71M
        }
3345
4.71M
        return current;
3346
4.71M
    }
3347
3348
    /*!
3349
    @brief unget current character (read it again on next get)
3350
3351
    We implement unget by setting variable next_unget to true. The input is not
3352
    changed - we just simulate ungetting by modifying chars_read and
3353
    token_string. The next call to get() will behave as if the unget character
3354
    is read again.
3355
    */
3356
    void unget()
3357
144k
    {
3358
144k
        next_unget = true;
3359
144k
        --chars_read;
3360
144k
        if (JSON_LIKELY(current != std::char_traits<char>::eof()))
3361
144k
        {
3362
144k
            assert(token_string.size() != 0);
3363
144k
            token_string.pop_back();
3364
144k
        }
3365
144k
    }
3366
3367
    /// add a character to token_buffer
3368
    void add(int c)
3369
3.18M
    {
3370
3.18M
        token_buffer.push_back(std::char_traits<char>::to_char_type(c));
3371
3.18M
    }
3372
3373
  public:
3374
    /////////////////////
3375
    // value getters
3376
    /////////////////////
3377
3378
    /// return integer value
3379
    constexpr number_integer_t get_number_integer() const noexcept
3380
9.18k
    {
3381
9.18k
        return value_integer;
3382
9.18k
    }
3383
3384
    /// return unsigned integer value
3385
    constexpr number_unsigned_t get_number_unsigned() const noexcept
3386
77.0k
    {
3387
77.0k
        return value_unsigned;
3388
77.0k
    }
3389
3390
    /// return floating-point value
3391
    constexpr number_float_t get_number_float() const noexcept
3392
57.4k
    {
3393
57.4k
        return value_float;
3394
57.4k
    }
3395
3396
    /// return current string value (implicitly resets the token; useful only once)
3397
    string_t& get_string()
3398
366k
    {
3399
366k
        return token_buffer;
3400
366k
    }
3401
3402
    /////////////////////
3403
    // diagnostics
3404
    /////////////////////
3405
3406
    /// return position of last read token
3407
    constexpr std::size_t get_position() const noexcept
3408
2
    {
3409
2
        return chars_read;
3410
2
    }
3411
3412
    /// return the last read token (for errors only).  Will never contain EOF
3413
    /// (an arbitrary value that is not a valid char value, often -1), because
3414
    /// 255 may legitimately occur.  May contain NUL, which should be escaped.
3415
    std::string get_token_string() const
3416
1
    {
3417
1
        // escape control characters
3418
1
        std::string result;
3419
1
        for (const auto c : token_string)
3420
1
        {
3421
0
            if ('\x00' <= c and c <= '\x1F')
3422
0
            {
3423
0
                // escape control characters
3424
0
                char cs[9];
3425
0
                snprintf(cs, 9, "<U+%.4X>", static_cast<unsigned char>(c));
3426
0
                result += cs;
3427
0
            }
3428
0
            else
3429
0
            {
3430
0
                // add character as is
3431
0
                result.push_back(c);
3432
0
            }
3433
0
        }
3434
1
3435
1
        return result;
3436
1
    }
3437
3438
    /// return syntax error message
3439
    constexpr const char* get_error_message() const noexcept
3440
0
    {
3441
0
        return error_message;
3442
0
    }
3443
3444
    /////////////////////
3445
    // actual scanner
3446
    /////////////////////
3447
3448
    /*!
3449
    @brief skip the UTF-8 byte order mark
3450
    @return true iff there is no BOM or the correct BOM has been skipped
3451
    */
3452
    bool skip_bom()
3453
835
    {
3454
835
        if (get() == 0xEF)
3455
835
        {
3456
0
            if (get() == 0xBB and get() == 0xBF)
3457
0
            {
3458
0
                // we completely parsed the BOM
3459
0
                return true;
3460
0
            }
3461
0
            else
3462
0
            {
3463
0
                // after reading 0xEF, an unexpected character followed
3464
0
                return false;
3465
0
            }
3466
0
        }
3467
835
        else
3468
835
        {
3469
835
            // the first character is not the beginning of the BOM; unget it to
3470
835
            // process is later
3471
835
            unget();
3472
835
            return true;
3473
835
        }
3474
835
    }
3475
3476
    token_type scan()
3477
1.01M
    {
3478
1.01M
        // initially, skip the BOM
3479
1.01M
        if (chars_read == 0 and not skip_bom())
3480
1.01M
        {
3481
0
            error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
3482
0
            return token_type::parse_error;
3483
0
        }
3484
1.01M
3485
1.01M
        // read next character and ignore whitespace
3486
1.01M
        do
3487
1.21M
        {
3488
1.21M
            get();
3489
1.21M
        }
3490
1.21M
        while (current == ' ' or current == '\t' or current == '\n' or current == '\r');
3491
1.01M
3492
1.01M
        switch (current)
3493
0
        {
3494
0
            // structural characters
3495
601
            case '[':
3496
601
                return token_type::begin_array;
3497
601
            case ']':
3498
601
                return token_type::end_array;
3499
50.8k
            case '{':
3500
50.8k
                return token_type::begin_object;
3501
50.8k
            case '}':
3502
50.8k
                return token_type::end_object;
3503
247k
            case ':':
3504
247k
                return token_type::name_separator;
3505
205k
            case ',':
3506
205k
                return token_type::value_separator;
3507
601
3508
601
            // literals
3509
602
            case 't':
3510
602
                return scan_literal("true", 4, token_type::literal_true);
3511
601
            case 'f':
3512
0
                return scan_literal("false", 5, token_type::literal_false);
3513
601
            case 'n':
3514
402
                return scan_literal("null", 4, token_type::literal_null);
3515
601
3516
601
            // string
3517
309k
            case '\"':
3518
309k
                return scan_string();
3519
601
3520
601
            // number
3521
143k
            case '-':
3522
143k
            case '0':
3523
143k
            case '1':
3524
143k
            case '2':
3525
143k
            case '3':
3526
143k
            case '4':
3527
143k
            case '5':
3528
143k
            case '6':
3529
143k
            case '7':
3530
143k
            case '8':
3531
143k
            case '9':
3532
143k
                return scan_number();
3533
143k
3534
143k
            // end of input (the null byte is needed when parsing from
3535
143k
            // string literals)
3536
143k
            case '\0':
3537
638
            case std::char_traits<char>::eof():
3538
638
                return token_type::end_of_input;
3539
638
3540
638
            // error
3541
638
            default:
3542
0
                error_message = "invalid literal";
3543
0
                return token_type::parse_error;
3544
0
        }
3545
1.01M
    }
3546
3547
  private:
3548
    /// input adapter
3549
    detail::input_adapter_t ia = nullptr;
3550
3551
    /// the current character
3552
    std::char_traits<char>::int_type current = std::char_traits<char>::eof();
3553
3554
    /// whether the next get() call should just return current
3555
    bool next_unget = false;
3556
3557
    /// the number of characters read
3558
    std::size_t chars_read = 0;
3559
3560
    /// raw input token string (for error messages)
3561
    std::vector<char> token_string {};
3562
3563
    /// buffer for variable-length tokens (numbers, strings)
3564
    string_t token_buffer {};
3565
3566
    /// a description of occurred lexer errors
3567
    const char* error_message = "";
3568
3569
    // number values
3570
    number_integer_t value_integer = 0;
3571
    number_unsigned_t value_unsigned = 0;
3572
    number_float_t value_float = 0;
3573
3574
    /// the decimal point
3575
    const char decimal_point_char = '.';
3576
};
3577
}
3578
}
3579
3580
// #include <nlohmann/detail/input/parser.hpp>
3581
3582
3583
#include <cassert> // assert
3584
#include <cmath> // isfinite
3585
#include <cstdint> // uint8_t
3586
#include <functional> // function
3587
#include <string> // string
3588
#include <utility> // move
3589
3590
// #include <nlohmann/detail/exceptions.hpp>
3591
3592
// #include <nlohmann/detail/macro_scope.hpp>
3593
3594
// #include <nlohmann/detail/meta/is_sax.hpp>
3595
3596
3597
#include <cstdint> // size_t
3598
#include <utility> // declval
3599
3600
// #include <nlohmann/detail/meta/detected.hpp>
3601
3602
// #include <nlohmann/detail/meta/type_traits.hpp>
3603
3604
3605
namespace nlohmann
3606
{
3607
namespace detail
3608
{
3609
template <typename T>
3610
using null_function_t = decltype(std::declval<T&>().null());
3611
3612
template <typename T>
3613
using boolean_function_t =
3614
    decltype(std::declval<T&>().boolean(std::declval<bool>()));
3615
3616
template <typename T, typename Integer>
3617
using number_integer_function_t =
3618
    decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
3619
3620
template <typename T, typename Unsigned>
3621
using number_unsigned_function_t =
3622
    decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
3623
3624
template <typename T, typename Float, typename String>
3625
using number_float_function_t = decltype(std::declval<T&>().number_float(
3626
                                    std::declval<Float>(), std::declval<const String&>()));
3627
3628
template <typename T, typename String>
3629
using string_function_t =
3630
    decltype(std::declval<T&>().string(std::declval<String&>()));
3631
3632
template <typename T>
3633
using start_object_function_t =
3634
    decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
3635
3636
template <typename T, typename String>
3637
using key_function_t =
3638
    decltype(std::declval<T&>().key(std::declval<String&>()));
3639
3640
template <typename T>
3641
using end_object_function_t = decltype(std::declval<T&>().end_object());
3642
3643
template <typename T>
3644
using start_array_function_t =
3645
    decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
3646
3647
template <typename T>
3648
using end_array_function_t = decltype(std::declval<T&>().end_array());
3649
3650
template <typename T, typename Exception>
3651
using parse_error_function_t = decltype(std::declval<T&>().parse_error(
3652
        std::declval<std::size_t>(), std::declval<const std::string&>(),
3653
        std::declval<const Exception&>()));
3654
3655
template <typename SAX, typename BasicJsonType>
3656
struct is_sax
3657
{
3658
  private:
3659
    static_assert(is_basic_json<BasicJsonType>::value,
3660
                  "BasicJsonType must be of type basic_json<...>");
3661
3662
    using number_integer_t = typename BasicJsonType::number_integer_t;
3663
    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
3664
    using number_float_t = typename BasicJsonType::number_float_t;
3665
    using string_t = typename BasicJsonType::string_t;
3666
    using exception_t = typename BasicJsonType::exception;
3667
3668
  public:
3669
    static constexpr bool value =
3670
        is_detected_exact<bool, null_function_t, SAX>::value &&
3671
        is_detected_exact<bool, boolean_function_t, SAX>::value &&
3672
        is_detected_exact<bool, number_integer_function_t, SAX,
3673
        number_integer_t>::value &&
3674
        is_detected_exact<bool, number_unsigned_function_t, SAX,
3675
        number_unsigned_t>::value &&
3676
        is_detected_exact<bool, number_float_function_t, SAX, number_float_t,
3677
        string_t>::value &&
3678
        is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
3679
        is_detected_exact<bool, start_object_function_t, SAX>::value &&
3680
        is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
3681
        is_detected_exact<bool, end_object_function_t, SAX>::value &&
3682
        is_detected_exact<bool, start_array_function_t, SAX>::value &&
3683
        is_detected_exact<bool, end_array_function_t, SAX>::value &&
3684
        is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
3685
};
3686
3687
template <typename SAX, typename BasicJsonType>
3688
struct is_sax_static_asserts
3689
{
3690
  private:
3691
    static_assert(is_basic_json<BasicJsonType>::value,
3692
                  "BasicJsonType must be of type basic_json<...>");
3693
3694
    using number_integer_t = typename BasicJsonType::number_integer_t;
3695
    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
3696
    using number_float_t = typename BasicJsonType::number_float_t;
3697
    using string_t = typename BasicJsonType::string_t;
3698
    using exception_t = typename BasicJsonType::exception;
3699
3700
  public:
3701
    static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
3702
                  "Missing/invalid function: bool null()");
3703
    static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
3704
                  "Missing/invalid function: bool boolean(bool)");
3705
    static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
3706
                  "Missing/invalid function: bool boolean(bool)");
3707
    static_assert(
3708
        is_detected_exact<bool, number_integer_function_t, SAX,
3709
        number_integer_t>::value,
3710
        "Missing/invalid function: bool number_integer(number_integer_t)");
3711
    static_assert(
3712
        is_detected_exact<bool, number_unsigned_function_t, SAX,
3713
        number_unsigned_t>::value,
3714
        "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
3715
    static_assert(is_detected_exact<bool, number_float_function_t, SAX,
3716
                  number_float_t, string_t>::value,
3717
                  "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
3718
    static_assert(
3719
        is_detected_exact<bool, string_function_t, SAX, string_t>::value,
3720
        "Missing/invalid function: bool string(string_t&)");
3721
    static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
3722
                  "Missing/invalid function: bool start_object(std::size_t)");
3723
    static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
3724
                  "Missing/invalid function: bool key(string_t&)");
3725
    static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
3726
                  "Missing/invalid function: bool end_object()");
3727
    static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
3728
                  "Missing/invalid function: bool start_array(std::size_t)");
3729
    static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
3730
                  "Missing/invalid function: bool end_array()");
3731
    static_assert(
3732
        is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
3733
        "Missing/invalid function: bool parse_error(std::size_t, const "
3734
        "std::string&, const exception&)");
3735
};
3736
}
3737
}
3738
3739
// #include <nlohmann/detail/input/input_adapters.hpp>
3740
3741
// #include <nlohmann/detail/input/json_sax.hpp>
3742
3743
3744
#include <cstddef>
3745
#include <string>
3746
#include <vector>
3747
3748
// #include <nlohmann/detail/input/parser.hpp>
3749
3750
// #include <nlohmann/detail/exceptions.hpp>
3751
3752
3753
namespace nlohmann
3754
{
3755
3756
/*!
3757
@brief SAX interface
3758
3759
This class describes the SAX interface used by @ref nlohmann::json::sax_parse.
3760
Each function is called in different situations while the input is parsed. The
3761
boolean return value informs the parser whether to continue processing the
3762
input.
3763
*/
3764
template<typename BasicJsonType>
3765
struct json_sax
3766
{
3767
    /// type for (signed) integers
3768
    using number_integer_t = typename BasicJsonType::number_integer_t;
3769
    /// type for unsigned integers
3770
    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
3771
    /// type for floating-point numbers
3772
    using number_float_t = typename BasicJsonType::number_float_t;
3773
    /// type for strings
3774
    using string_t = typename BasicJsonType::string_t;
3775
3776
    /*!
3777
    @brief a null value was read
3778
    @return whether parsing should proceed
3779
    */
3780
    virtual bool null() = 0;
3781
3782
    /*!
3783
    @brief a boolean value was read
3784
    @param[in] val  boolean value
3785
    @return whether parsing should proceed
3786
    */
3787
    virtual bool boolean(bool val) = 0;
3788
3789
    /*!
3790
    @brief an integer number was read
3791
    @param[in] val  integer value
3792
    @return whether parsing should proceed
3793
    */
3794
    virtual bool number_integer(number_integer_t val) = 0;
3795
3796
    /*!
3797
    @brief an unsigned integer number was read
3798
    @param[in] val  unsigned integer value
3799
    @return whether parsing should proceed
3800
    */
3801
    virtual bool number_unsigned(number_unsigned_t val) = 0;
3802
3803
    /*!
3804
    @brief an floating-point number was read
3805
    @param[in] val  floating-point value
3806
    @param[in] s    raw token value
3807
    @return whether parsing should proceed
3808
    */
3809
    virtual bool number_float(number_float_t val, const string_t& s) = 0;
3810
3811
    /*!
3812
    @brief a string was read
3813
    @param[in] val  string value
3814
    @return whether parsing should proceed
3815
    @note It is safe to move the passed string.
3816
    */
3817
    virtual bool string(string_t& val) = 0;
3818
3819
    /*!
3820
    @brief the beginning of an object was read
3821
    @param[in] elements  number of object elements or -1 if unknown
3822
    @return whether parsing should proceed
3823
    @note binary formats may report the number of elements
3824
    */
3825
    virtual bool start_object(std::size_t elements) = 0;
3826
3827
    /*!
3828
    @brief an object key was read
3829
    @param[in] val  object key
3830
    @return whether parsing should proceed
3831
    @note It is safe to move the passed string.
3832
    */
3833
    virtual bool key(string_t& val) = 0;
3834
3835
    /*!
3836
    @brief the end of an object was read
3837
    @return whether parsing should proceed
3838
    */
3839
    virtual bool end_object() = 0;
3840
3841
    /*!
3842
    @brief the beginning of an array was read
3843
    @param[in] elements  number of array elements or -1 if unknown
3844
    @return whether parsing should proceed
3845
    @note binary formats may report the number of elements
3846
    */
3847
    virtual bool start_array(std::size_t elements) = 0;
3848
3849
    /*!
3850
    @brief the end of an array was read
3851
    @return whether parsing should proceed
3852
    */
3853
    virtual bool end_array() = 0;
3854
3855
    /*!
3856
    @brief a parse error occurred
3857
    @param[in] position    the position in the input where the error occurs
3858
    @param[in] last_token  the last read token
3859
    @param[in] error_msg   a detailed error message
3860
    @return whether parsing should proceed (must return false)
3861
    */
3862
    virtual bool parse_error(std::size_t position,
3863
                             const std::string& last_token,
3864
                             const detail::exception& ex) = 0;
3865
3866
    virtual ~json_sax() = default;
3867
};
3868
3869
3870
namespace detail
3871
{
3872
/*!
3873
@brief SAX implementation to create a JSON value from SAX events
3874
3875
This class implements the @ref json_sax interface and processes the SAX events
3876
to create a JSON value which makes it basically a DOM parser. The structure or
3877
hierarchy of the JSON value is managed by the stack `ref_stack` which contains
3878
a pointer to the respective array or object for each recursion depth.
3879
3880
After successful parsing, the value that is passed by reference to the
3881
constructor contains the parsed value.
3882
3883
@tparam BasicJsonType  the JSON type
3884
*/
3885
template<typename BasicJsonType>
3886
class json_sax_dom_parser
3887
{
3888
  public:
3889
    using number_integer_t = typename BasicJsonType::number_integer_t;
3890
    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
3891
    using number_float_t = typename BasicJsonType::number_float_t;
3892
    using string_t = typename BasicJsonType::string_t;
3893
3894
    /*!
3895
    @param[in, out] r  reference to a JSON value that is manipulated while
3896
                       parsing
3897
    @param[in] allow_exceptions_  whether parse errors yield exceptions
3898
    */
3899
    explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
3900
        : root(r), allow_exceptions(allow_exceptions_)
3901
835
    {}
3902
3903
    bool null()
3904
402
    {
3905
402
        handle_value(nullptr);
3906
402
        return true;
3907
402
    }
3908
3909
    bool boolean(bool val)
3910
602
    {
3911
602
        handle_value(val);
3912
602
        return true;
3913
602
    }
3914
3915
    bool number_integer(number_integer_t val)
3916
9.18k
    {
3917
9.18k
        handle_value(val);
3918
9.18k
        return true;
3919
9.18k
    }
3920
3921
    bool number_unsigned(number_unsigned_t val)
3922
77.0k
    {
3923
77.0k
        handle_value(val);
3924
77.0k
        return true;
3925
77.0k
    }
3926
3927
    bool number_float(number_float_t val, const string_t&)
3928
57.4k
    {
3929
57.4k
        handle_value(val);
3930
57.4k
        return true;
3931
57.4k
    }
3932
3933
    bool string(string_t& val)
3934
61.8k
    {
3935
61.8k
        handle_value(val);
3936
61.8k
        return true;
3937
61.8k
    }
3938
3939
    bool start_object(std::size_t len)
3940
50.8k
    {
3941
50.8k
        ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
3942
50.8k
3943
50.8k
        if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
3944
50.8k
        {
3945
0
            JSON_THROW(out_of_range::create(408,
3946
0
                                            "excessive object size: " + std::to_string(len)));
3947
0
        }
3948
50.8k
3949
50.8k
        return true;
3950
50.8k
    }
3951
3952
    bool key(string_t& val)
3953
247k
    {
3954
247k
        // add null at given key and store the reference for later
3955
247k
        object_element = &(ref_stack.back()->m_value.object->operator[](val));
3956
247k
        return true;
3957
247k
    }
3958
3959
    bool end_object()
3960
50.8k
    {
3961
50.8k
        ref_stack.pop_back();
3962
50.8k
        return true;
3963
50.8k
    }
3964
3965
    bool start_array(std::size_t len)
3966
601
    {
3967
601
        ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
3968
601
3969
601
        if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
3970
601
        {
3971
0
            JSON_THROW(out_of_range::create(408,
3972
0
                                            "excessive array size: " + std::to_string(len)));
3973
0
        }
3974
601
3975
601
        return true;
3976
601
    }
3977
3978
    bool end_array()
3979
601
    {
3980
601
        ref_stack.pop_back();
3981
601
        return true;
3982
601
    }
3983
3984
    bool parse_error(std::size_t, const std::string&,
3985
                     const detail::exception& ex)
3986
1
    {
3987
1
        errored = true;
3988
1
        if (allow_exceptions)
3989
1
        {
3990
1
            // determine the proper exception type from the id
3991
1
            switch ((ex.id / 100) % 100)
3992
0
            {
3993
1
                case 1:
3994
1
                    JSON_THROW(*reinterpret_cast<const detail::parse_error*>(&ex));
3995
1
                case 4:
3996
0
                    JSON_THROW(*reinterpret_cast<const detail::out_of_range*>(&ex));
3997
1
                // LCOV_EXCL_START
3998
1
                case 2:
3999
0
                    JSON_THROW(*reinterpret_cast<const detail::invalid_iterator*>(&ex));
4000
1
                case 3:
4001
0
                    JSON_THROW(*reinterpret_cast<const detail::type_error*>(&ex));
4002
1
                case 5:
4003
0
                    JSON_THROW(*reinterpret_cast<const detail::other_error*>(&ex));
4004
1
                default:
4005
0
                    assert(false);
4006
0
                    // LCOV_EXCL_STOP
4007
0
            }
4008
1
        }
4009
1
        return false;
4010
1
    }
4011
4012
    constexpr bool is_errored() const
4013
834
    {
4014
834
        return errored;
4015
834
    }
4016
4017
  private:
4018
    /*!
4019
    @invariant If the ref stack is empty, then the passed value will be the new
4020
               root.
4021
    @invariant If the ref stack contains a value, then it is an array or an
4022
               object to which we can add elements
4023
    */
4024
    template<typename Value>
4025
    BasicJsonType* handle_value(Value&& v)
4026
257k
    {
4027
257k
        if (ref_stack.empty())
4028
257k
        {
4029
834
            root = BasicJsonType(std::forward<Value>(v));
4030
834
            return &root;
4031
834
        }
4032
257k
        else
4033
257k
        {
4034
257k
            assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
4035
257k
            if (ref_stack.back()->is_array())
4036
257k
            {
4037
9.57k
                ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
4038
9.57k
                return &(ref_stack.back()->m_value.array->back());
4039
9.57k
            }
4040
257k
            else
4041
257k
            {
4042
247k
                assert(object_element);
4043
247k
                *object_element = BasicJsonType(std::forward<Value>(v));
4044
247k
                return object_element;
4045
247k
            }
4046
257k
        }
4047
257k
    }
_ZN8nlohmann6detail19json_sax_dom_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEE12handle_valueIDnEEPSC_OT_
Line
Count
Source
4026
402
    {
4027
402
        if (ref_stack.empty())
4028
402
        {
4029
0
            root = BasicJsonType(std::forward<Value>(v));
4030
0
            return &root;
4031
0
        }
4032
402
        else
4033
402
        {
4034
402
            assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
4035
402
            if (ref_stack.back()->is_array())
4036
402
            {
4037
0
                ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
4038
0
                return &(ref_stack.back()->m_value.array->back());
4039
0
            }
4040
402
            else
4041
402
            {
4042
402
                assert(object_element);
4043
402
                *object_element = BasicJsonType(std::forward<Value>(v));
4044
402
                return object_element;
4045
402
            }
4046
402
        }
4047
402
    }
_ZN8nlohmann6detail19json_sax_dom_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEE12handle_valueIRlEEPSC_OT_
Line
Count
Source
4026
9.18k
    {
4027
9.18k
        if (ref_stack.empty())
4028
9.18k
        {
4029
0
            root = BasicJsonType(std::forward<Value>(v));
4030
0
            return &root;
4031
0
        }
4032
9.18k
        else
4033
9.18k
        {
4034
9.18k
            assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
4035
9.18k
            if (ref_stack.back()->is_array())
4036
9.18k
            {
4037
0
                ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
4038
0
                return &(ref_stack.back()->m_value.array->back());
4039
0
            }
4040
9.18k
            else
4041
9.18k
            {
4042
9.18k
                assert(object_element);
4043
9.18k
                *object_element = BasicJsonType(std::forward<Value>(v));
4044
9.18k
                return object_element;
4045
9.18k
            }
4046
9.18k
        }
4047
9.18k
    }
_ZN8nlohmann6detail19json_sax_dom_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEE12handle_valueIRbEEPSC_OT_
Line
Count
Source
4026
602
    {
4027
602
        if (ref_stack.empty())
4028
602
        {
4029
0
            root = BasicJsonType(std::forward<Value>(v));
4030
0
            return &root;
4031
0
        }
4032
602
        else
4033
602
        {
4034
602
            assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
4035
602
            if (ref_stack.back()->is_array())
4036
602
            {
4037
0
                ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
4038
0
                return &(ref_stack.back()->m_value.array->back());
4039
0
            }
4040
602
            else
4041
602
            {
4042
602
                assert(object_element);
4043
602
                *object_element = BasicJsonType(std::forward<Value>(v));
4044
602
                return object_element;
4045
602
            }
4046
602
        }
4047
602
    }
_ZN8nlohmann6detail19json_sax_dom_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEE12handle_valueIRdEEPSC_OT_
Line
Count
Source
4026
57.4k
    {
4027
57.4k
        if (ref_stack.empty())
4028
57.4k
        {
4029
0
            root = BasicJsonType(std::forward<Value>(v));
4030
0
            return &root;
4031
0
        }
4032
57.4k
        else
4033
57.4k
        {
4034
57.4k
            assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
4035
57.4k
            if (ref_stack.back()->is_array())
4036
57.4k
            {
4037
0
                ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
4038
0
                return &(ref_stack.back()->m_value.array->back());
4039
0
            }
4040
57.4k
            else
4041
57.4k
            {
4042
57.4k
                assert(object_element);
4043
57.4k
                *object_element = BasicJsonType(std::forward<Value>(v));
4044
57.4k
                return object_element;
4045
57.4k
            }
4046
57.4k
        }
4047
57.4k
    }
_ZN8nlohmann6detail19json_sax_dom_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEE12handle_valueINS0_7value_tEEEPSC_OT_
Line
Count
Source
4026
51.4k
    {
4027
51.4k
        if (ref_stack.empty())
4028
51.4k
        {
4029
834
            root = BasicJsonType(std::forward<Value>(v));
4030
834
            return &root;
4031
834
        }
4032
51.4k
        else
4033
51.4k
        {
4034
50.6k
            assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
4035
50.6k
            if (ref_stack.back()->is_array())
4036
50.6k
            {
4037
9.57k
                ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
4038
9.57k
                return &(ref_stack.back()->m_value.array->back());
4039
9.57k
            }
4040
50.6k
            else
4041
50.6k
            {
4042
41.0k
                assert(object_element);
4043
41.0k
                *object_element = BasicJsonType(std::forward<Value>(v));
4044
41.0k
                return object_element;
4045
41.0k
            }
4046
50.6k
        }
4047
51.4k
    }
_ZN8nlohmann6detail19json_sax_dom_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEE12handle_valueIRmEEPSC_OT_
Line
Count
Source
4026
77.0k
    {
4027
77.0k
        if (ref_stack.empty())
4028
77.0k
        {
4029
0
            root = BasicJsonType(std::forward<Value>(v));
4030
0
            return &root;
4031
0
        }
4032
77.0k
        else
4033
77.0k
        {
4034
77.0k
            assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
4035
77.0k
            if (ref_stack.back()->is_array())
4036
77.0k
            {
4037
0
                ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
4038
0
                return &(ref_stack.back()->m_value.array->back());
4039
0
            }
4040
77.0k
            else
4041
77.0k
            {
4042
77.0k
                assert(object_element);
4043
77.0k
                *object_element = BasicJsonType(std::forward<Value>(v));
4044
77.0k
                return object_element;
4045
77.0k
            }
4046
77.0k
        }
4047
77.0k
    }
_ZN8nlohmann6detail19json_sax_dom_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEE12handle_valueIRSA_EEPSC_OT_
Line
Count
Source
4026
61.8k
    {
4027
61.8k
        if (ref_stack.empty())
4028
61.8k
        {
4029
0
            root = BasicJsonType(std::forward<Value>(v));
4030
0
            return &root;
4031
0
        }
4032
61.8k
        else
4033
61.8k
        {
4034
61.8k
            assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
4035
61.8k
            if (ref_stack.back()->is_array())
4036
61.8k
            {
4037
0
                ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
4038
0
                return &(ref_stack.back()->m_value.array->back());
4039
0
            }
4040
61.8k
            else
4041
61.8k
            {
4042
61.8k
                assert(object_element);
4043
61.8k
                *object_element = BasicJsonType(std::forward<Value>(v));
4044
61.8k
                return object_element;
4045
61.8k
            }
4046
61.8k
        }
4047
61.8k
    }
4048
4049
    /// the parsed JSON value
4050
    BasicJsonType& root;
4051
    /// stack to model hierarchy of values
4052
    std::vector<BasicJsonType*> ref_stack;
4053
    /// helper to hold the reference for the next object element
4054
    BasicJsonType* object_element = nullptr;
4055
    /// whether a syntax error occurred
4056
    bool errored = false;
4057
    /// whether to throw exceptions in case of errors
4058
    const bool allow_exceptions = true;
4059
};
4060
4061
template<typename BasicJsonType>
4062
class json_sax_dom_callback_parser
4063
{
4064
  public:
4065
    using number_integer_t = typename BasicJsonType::number_integer_t;
4066
    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
4067
    using number_float_t = typename BasicJsonType::number_float_t;
4068
    using string_t = typename BasicJsonType::string_t;
4069
    using parser_callback_t = typename BasicJsonType::parser_callback_t;
4070
    using parse_event_t = typename BasicJsonType::parse_event_t;
4071
4072
    json_sax_dom_callback_parser(BasicJsonType& r,
4073
                                 const parser_callback_t cb,
4074
                                 const bool allow_exceptions_ = true)
4075
        : root(r), callback(cb), allow_exceptions(allow_exceptions_)
4076
0
    {
4077
0
        keep_stack.push_back(true);
4078
0
    }
4079
4080
    bool null()
4081
0
    {
4082
0
        handle_value(nullptr);
4083
0
        return true;
4084
0
    }
4085
4086
    bool boolean(bool val)
4087
0
    {
4088
0
        handle_value(val);
4089
0
        return true;
4090
0
    }
4091
4092
    bool number_integer(number_integer_t val)
4093
0
    {
4094
0
        handle_value(val);
4095
0
        return true;
4096
0
    }
4097
4098
    bool number_unsigned(number_unsigned_t val)
4099
0
    {
4100
0
        handle_value(val);
4101
0
        return true;
4102
0
    }
4103
4104
    bool number_float(number_float_t val, const string_t&)
4105
0
    {
4106
0
        handle_value(val);
4107
0
        return true;
4108
0
    }
4109
4110
    bool string(string_t& val)
4111
0
    {
4112
0
        handle_value(val);
4113
0
        return true;
4114
0
    }
4115
4116
    bool start_object(std::size_t len)
4117
0
    {
4118
0
        // check callback for object start
4119
0
        const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
4120
0
        keep_stack.push_back(keep);
4121
0
4122
0
        auto val = handle_value(BasicJsonType::value_t::object, true);
4123
0
        ref_stack.push_back(val.second);
4124
0
4125
0
        // check object limit
4126
0
        if (ref_stack.back())
4127
0
        {
4128
0
            if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
4129
0
            {
4130
0
                JSON_THROW(out_of_range::create(408,
4131
0
                                                "excessive object size: " + std::to_string(len)));
4132
0
            }
4133
0
        }
4134
0
4135
0
        return true;
4136
0
    }
4137
4138
    bool key(string_t& val)
4139
0
    {
4140
0
        BasicJsonType k = BasicJsonType(val);
4141
0
4142
0
        // check callback for key
4143
0
        const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
4144
0
        key_keep_stack.push_back(keep);
4145
0
4146
0
        // add discarded value at given key and store the reference for later
4147
0
        if (keep and ref_stack.back())
4148
0
        {
4149
0
            object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded);
4150
0
        }
4151
0
4152
0
        return true;
4153
0
    }
4154
4155
    bool end_object()
4156
0
    {
4157
0
        if (ref_stack.back())
4158
0
        {
4159
0
            if (not callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
4160
0
            {
4161
0
                // discard object
4162
0
                *ref_stack.back() = discarded;
4163
0
            }
4164
0
        }
4165
0
4166
0
        assert(not ref_stack.empty());
4167
0
        assert(not keep_stack.empty());
4168
0
        ref_stack.pop_back();
4169
0
        keep_stack.pop_back();
4170
0
4171
0
        if (not ref_stack.empty() and ref_stack.back())
4172
0
        {
4173
0
            // remove discarded value
4174
0
            if (ref_stack.back()->is_object())
4175
0
            {
4176
0
                for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
4177
0
                {
4178
0
                    if (it->is_discarded())
4179
0
                    {
4180
0
                        ref_stack.back()->erase(it);
4181
0
                        break;
4182
0
                    }
4183
0
                }
4184
0
            }
4185
0
        }
4186
0
4187
0
        return true;
4188
0
    }
4189
4190
    bool start_array(std::size_t len)
4191
0
    {
4192
0
        const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
4193
0
        keep_stack.push_back(keep);
4194
0
4195
0
        auto val = handle_value(BasicJsonType::value_t::array, true);
4196
0
        ref_stack.push_back(val.second);
4197
0
4198
0
        // check array limit
4199
0
        if (ref_stack.back())
4200
0
        {
4201
0
            if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
4202
0
            {
4203
0
                JSON_THROW(out_of_range::create(408,
4204
0
                                                "excessive array size: " + std::to_string(len)));
4205
0
            }
4206
0
        }
4207
0
4208
0
        return true;
4209
0
    }
4210
4211
    bool end_array()
4212
0
    {
4213
0
        bool keep = true;
4214
0
4215
0
        if (ref_stack.back())
4216
0
        {
4217
0
            keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
4218
0
            if (not keep)
4219
0
            {
4220
0
                // discard array
4221
0
                *ref_stack.back() = discarded;
4222
0
            }
4223
0
        }
4224
0
4225
0
        assert(not ref_stack.empty());
4226
0
        assert(not keep_stack.empty());
4227
0
        ref_stack.pop_back();
4228
0
        keep_stack.pop_back();
4229
0
4230
0
        // remove discarded value
4231
0
        if (not keep and not ref_stack.empty())
4232
0
        {
4233
0
            if (ref_stack.back()->is_array())
4234
0
            {
4235
0
                ref_stack.back()->m_value.array->pop_back();
4236
0
            }
4237
0
        }
4238
0
4239
0
        return true;
4240
0
    }
4241
4242
    bool parse_error(std::size_t, const std::string&,
4243
                     const detail::exception& ex)
4244
0
    {
4245
0
        errored = true;
4246
0
        if (allow_exceptions)
4247
0
        {
4248
0
            // determine the proper exception type from the id
4249
0
            switch ((ex.id / 100) % 100)
4250
0
            {
4251
0
                case 1:
4252
0
                    JSON_THROW(*reinterpret_cast<const detail::parse_error*>(&ex));
4253
0
                case 4:
4254
0
                    JSON_THROW(*reinterpret_cast<const detail::out_of_range*>(&ex));
4255
0
                // LCOV_EXCL_START
4256
0
                case 2:
4257
0
                    JSON_THROW(*reinterpret_cast<const detail::invalid_iterator*>(&ex));
4258
0
                case 3:
4259
0
                    JSON_THROW(*reinterpret_cast<const detail::type_error*>(&ex));
4260
0
                case 5:
4261
0
                    JSON_THROW(*reinterpret_cast<const detail::other_error*>(&ex));
4262
0
                default:
4263
0
                    assert(false);
4264
0
                    // LCOV_EXCL_STOP
4265
0
            }
4266
0
        }
4267
0
        return false;
4268
0
    }
4269
4270
    constexpr bool is_errored() const
4271
0
    {
4272
0
        return errored;
4273
0
    }
4274
4275
  private:
4276
    /*!
4277
    @param[in] v  value to add to the JSON value we build during parsing
4278
    @param[in] skip_callback  whether we should skip calling the callback
4279
               function; this is required after start_array() and
4280
               start_object() SAX events, because otherwise we would call the
4281
               callback function with an empty array or object, respectively.
4282
4283
    @invariant If the ref stack is empty, then the passed value will be the new
4284
               root.
4285
    @invariant If the ref stack contains a value, then it is an array or an
4286
               object to which we can add elements
4287
4288
    @return pair of boolean (whether value should be kept) and pointer (to the
4289
            passed value in the ref_stack hierarchy; nullptr if not kept)
4290
    */
4291
    template<typename Value>
4292
    std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
4293
0
    {
4294
0
        assert(not keep_stack.empty());
4295
0
4296
0
        // do not handle this value if we know it would be added to a discarded
4297
0
        // container
4298
0
        if (not keep_stack.back())
4299
0
        {
4300
0
            return {false, nullptr};
4301
0
        }
4302
0
4303
0
        // create value
4304
0
        auto value = BasicJsonType(std::forward<Value>(v));
4305
0
4306
0
        // check callback
4307
0
        const bool keep = skip_callback or callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
4308
0
4309
0
        // do not handle this value if we just learnt it shall be discarded
4310
0
        if (not keep)
4311
0
        {
4312
0
            return {false, nullptr};
4313
0
        }
4314
0
4315
0
        if (ref_stack.empty())
4316
0
        {
4317
0
            root = std::move(value);
4318
0
            return {true, &root};
4319
0
        }
4320
0
        else
4321
0
        {
4322
0
            // skip this value if we already decided to skip the parent
4323
0
            // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
4324
0
            if (not ref_stack.back())
4325
0
            {
4326
0
                return {false, nullptr};
4327
0
            }
4328
0
4329
0
            assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
4330
0
            if (ref_stack.back()->is_array())
4331
0
            {
4332
0
                ref_stack.back()->m_value.array->push_back(std::move(value));
4333
0
                return {true, &(ref_stack.back()->m_value.array->back())};
4334
0
            }
4335
0
            else
4336
0
            {
4337
0
                // check if we should store an element for the current key
4338
0
                assert(not key_keep_stack.empty());
4339
0
                const bool store_element = key_keep_stack.back();
4340
0
                key_keep_stack.pop_back();
4341
0
4342
0
                if (not store_element)
4343
0
                {
4344
0
                    return {false, nullptr};
4345
0
                }
4346
0
4347
0
                assert(object_element);
4348
0
                *object_element = std::move(value);
4349
0
                return {true, object_element};
4350
0
            }
4351
0
        }
4352
0
    }
Unexecuted instantiation: _ZN8nlohmann6detail28json_sax_dom_callback_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEE12handle_valueIRlEESt4pairIbPSC_EOT_b
Unexecuted instantiation: _ZN8nlohmann6detail28json_sax_dom_callback_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEE12handle_valueIRmEESt4pairIbPSC_EOT_b
Unexecuted instantiation: _ZN8nlohmann6detail28json_sax_dom_callback_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEE12handle_valueIRSA_EESt4pairIbPSC_EOT_b
Unexecuted instantiation: _ZN8nlohmann6detail28json_sax_dom_callback_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEE12handle_valueIRbEESt4pairIbPSC_EOT_b
Unexecuted instantiation: _ZN8nlohmann6detail28json_sax_dom_callback_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEE12handle_valueINS0_7value_tEEESt4pairIbPSC_EOT_b
Unexecuted instantiation: _ZN8nlohmann6detail28json_sax_dom_callback_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEE12handle_valueIRdEESt4pairIbPSC_EOT_b
Unexecuted instantiation: _ZN8nlohmann6detail28json_sax_dom_callback_parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEE12handle_valueIDnEESt4pairIbPSC_EOT_b
4353
4354
    /// the parsed JSON value
4355
    BasicJsonType& root;
4356
    /// stack to model hierarchy of values
4357
    std::vector<BasicJsonType*> ref_stack;
4358
    /// stack to manage which values to keep
4359
    std::vector<bool> keep_stack;
4360
    /// stack to manage which object keys to keep
4361
    std::vector<bool> key_keep_stack;
4362
    /// helper to hold the reference for the next object element
4363
    BasicJsonType* object_element = nullptr;
4364
    /// whether a syntax error occurred
4365
    bool errored = false;
4366
    /// callback function
4367
    const parser_callback_t callback = nullptr;
4368
    /// whether to throw exceptions in case of errors
4369
    const bool allow_exceptions = true;
4370
    /// a discarded value for the callback
4371
    BasicJsonType discarded = BasicJsonType::value_t::discarded;
4372
};
4373
4374
template<typename BasicJsonType>
4375
class json_sax_acceptor
4376
{
4377
  public:
4378
    using number_integer_t = typename BasicJsonType::number_integer_t;
4379
    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
4380
    using number_float_t = typename BasicJsonType::number_float_t;
4381
    using string_t = typename BasicJsonType::string_t;
4382
4383
    bool null()
4384
    {
4385
        return true;
4386
    }
4387
4388
    bool boolean(bool)
4389
    {
4390
        return true;
4391
    }
4392
4393
    bool number_integer(number_integer_t)
4394
    {
4395
        return true;
4396
    }
4397
4398
    bool number_unsigned(number_unsigned_t)
4399
    {
4400
        return true;
4401
    }
4402
4403
    bool number_float(number_float_t, const string_t&)
4404
    {
4405
        return true;
4406
    }
4407
4408
    bool string(string_t&)
4409
    {
4410
        return true;
4411
    }
4412
4413
    bool start_object(std::size_t = std::size_t(-1))
4414
    {
4415
        return true;
4416
    }
4417
4418
    bool key(string_t&)
4419
    {
4420
        return true;
4421
    }
4422
4423
    bool end_object()
4424
    {
4425
        return true;
4426
    }
4427
4428
    bool start_array(std::size_t = std::size_t(-1))
4429
    {
4430
        return true;
4431
    }
4432
4433
    bool end_array()
4434
    {
4435
        return true;
4436
    }
4437
4438
    bool parse_error(std::size_t, const std::string&, const detail::exception&)
4439
    {
4440
        return false;
4441
    }
4442
};
4443
}
4444
4445
}
4446
4447
// #include <nlohmann/detail/input/lexer.hpp>
4448
4449
// #include <nlohmann/detail/value_t.hpp>
4450
4451
4452
namespace nlohmann
4453
{
4454
namespace detail
4455
{
4456
////////////
4457
// parser //
4458
////////////
4459
4460
/*!
4461
@brief syntax analysis
4462
4463
This class implements a recursive decent parser.
4464
*/
4465
template<typename BasicJsonType>
4466
class parser
4467
{
4468
    using number_integer_t = typename BasicJsonType::number_integer_t;
4469
    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
4470
    using number_float_t = typename BasicJsonType::number_float_t;
4471
    using string_t = typename BasicJsonType::string_t;
4472
    using lexer_t = lexer<BasicJsonType>;
4473
    using token_type = typename lexer_t::token_type;
4474
4475
  public:
4476
    enum class parse_event_t : uint8_t
4477
    {
4478
        /// the parser read `{` and started to process a JSON object
4479
        object_start,
4480
        /// the parser read `}` and finished processing a JSON object
4481
        object_end,
4482
        /// the parser read `[` and started to process a JSON array
4483
        array_start,
4484
        /// the parser read `]` and finished processing a JSON array
4485
        array_end,
4486
        /// the parser read a key of a value in an object
4487
        key,
4488
        /// the parser finished reading a JSON value
4489
        value
4490
    };
4491
4492
    using parser_callback_t =
4493
        std::function<bool(int depth, parse_event_t event, BasicJsonType& parsed)>;
4494
4495
    /// a parser reading from an input adapter
4496
    explicit parser(detail::input_adapter_t&& adapter,
4497
                    const parser_callback_t cb = nullptr,
4498
                    const bool allow_exceptions_ = true)
4499
        : callback(cb), m_lexer(std::move(adapter)), allow_exceptions(allow_exceptions_)
4500
835
    {
4501
835
        // read first token
4502
835
        get_token();
4503
835
    }
4504
4505
    /*!
4506
    @brief public parser interface
4507
4508
    @param[in] strict      whether to expect the last token to be EOF
4509
    @param[in,out] result  parsed JSON value
4510
4511
    @throw parse_error.101 in case of an unexpected token
4512
    @throw parse_error.102 if to_unicode fails or surrogate error
4513
    @throw parse_error.103 if to_unicode fails
4514
    */
4515
    void parse(const bool strict, BasicJsonType& result)
4516
835
    {
4517
835
        if (callback)
4518
835
        {
4519
0
            json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
4520
0
            sax_parse_internal(&sdp);
4521
0
            result.assert_invariant();
4522
0
4523
0
            // in strict mode, input must be completely read
4524
0
            if (strict and (get_token() != token_type::end_of_input))
4525
0
            {
4526
0
                sdp.parse_error(m_lexer.get_position(),
4527
0
                                m_lexer.get_token_string(),
4528
0
                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input)));
4529
0
            }
4530
0
4531
0
            // in case of an error, return discarded value
4532
0
            if (sdp.is_errored())
4533
0
            {
4534
0
                result = value_t::discarded;
4535
0
                return;
4536
0
            }
4537
0
4538
0
            // set top-level value to null if it was discarded by the callback
4539
0
            // function
4540
0
            if (result.is_discarded())
4541
0
            {
4542
0
                result = nullptr;
4543
0
            }
4544
0
        }
4545
835
        else
4546
835
        {
4547
835
            json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
4548
835
            sax_parse_internal(&sdp);
4549
835
            result.assert_invariant();
4550
835
4551
835
            // in strict mode, input must be completely read
4552
835
            if (strict and (get_token() != token_type::end_of_input))
4553
835
            {
4554
0
                sdp.parse_error(m_lexer.get_position(),
4555
0
                                m_lexer.get_token_string(),
4556
0
                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input)));
4557
0
            }
4558
835
4559
835
            // in case of an error, return discarded value
4560
835
            if (sdp.is_errored())
4561
835
            {
4562
0
                result = value_t::discarded;
4563
0
                return;
4564
0
            }
4565
835
        }
4566
835
    }
4567
4568
    /*!
4569
    @brief public accept interface
4570
4571
    @param[in] strict  whether to expect the last token to be EOF
4572
    @return whether the input is a proper JSON text
4573
    */
4574
    bool accept(const bool strict = true)
4575
    {
4576
        json_sax_acceptor<BasicJsonType> sax_acceptor;
4577
        return sax_parse(&sax_acceptor, strict);
4578
    }
4579
4580
    template <typename SAX>
4581
    bool sax_parse(SAX* sax, const bool strict = true)
4582
    {
4583
        (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
4584
        const bool result = sax_parse_internal(sax);
4585
4586
        // strict mode: next byte must be EOF
4587
        if (result and strict and (get_token() != token_type::end_of_input))
4588
        {
4589
            return sax->parse_error(m_lexer.get_position(),
4590
                                    m_lexer.get_token_string(),
4591
                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input)));
4592
        }
4593
4594
        return result;
4595
    }
4596
4597
  private:
4598
    template <typename SAX>
4599
    bool sax_parse_internal(SAX* sax)
4600
835
    {
4601
835
        // stack to remember the hieararchy of structured values we are parsing
4602
835
        // true = array; false = object
4603
835
        std::vector<bool> states;
4604
835
        // value to avoid a goto (see comment where set to true)
4605
835
        bool skip_to_state_evaluation = false;
4606
835
4607
309k
        while (true)
4608
309k
        {
4609
309k
            if (not skip_to_state_evaluation)
4610
309k
            {
4611
257k
                // invariant: get_token() was called before each iteration
4612
257k
                switch (last_token)
4613
206k
                {
4614
206k
                    case token_type::begin_object:
4615
50.8k
                    {
4616
50.8k
                        if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1))))
4617
50.8k
                        {
4618
0
                            return false;
4619
0
                        }
4620
50.8k
4621
50.8k
                        // closing } -> we are done
4622
50.8k
                        if (get_token() == token_type::end_object)
4623
50.8k
                        {
4624
0
                            if (JSON_UNLIKELY(not sax->end_object()))
4625
0
                            {
4626
0
                                return false;
4627
0
                            }
4628
0
                            break;
4629
0
                        }
4630
50.8k
4631
50.8k
                        // parse key
4632
50.8k
                        if (JSON_UNLIKELY(last_token != token_type::value_string))
4633
50.8k
                        {
4634
0
                            return sax->parse_error(m_lexer.get_position(),
4635
0
                                                    m_lexer.get_token_string(),
4636
0
                                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string)));
4637
0
                        }
4638
50.8k
                        else
4639
50.8k
                        {
4640
50.8k
                            if (JSON_UNLIKELY(not sax->key(m_lexer.get_string())))
4641
50.8k
                            {
4642
0
                                return false;
4643
0
                            }
4644
50.8k
                        }
4645
50.8k
4646
50.8k
                        // parse separator (:)
4647
50.8k
                        if (JSON_UNLIKELY(get_token() != token_type::name_separator))
4648
50.8k
                        {
4649
0
                            return sax->parse_error(m_lexer.get_position(),
4650
0
                                                    m_lexer.get_token_string(),
4651
0
                                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator)));
4652
0
                        }
4653
50.8k
4654
50.8k
                        // remember we are now inside an object
4655
50.8k
                        states.push_back(false);
4656
50.8k
4657
50.8k
                        // parse values
4658
50.8k
                        get_token();
4659
50.8k
                        continue;
4660
50.8k
                    }
4661
50.8k
4662
50.8k
                    case token_type::begin_array:
4663
601
                    {
4664
601
                        if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1))))
4665
601
                        {
4666
0
                            return false;
4667
0
                        }
4668
601
4669
601
                        // closing ] -> we are done
4670
601
                        if (get_token() == token_type::end_array)
4671
601
                        {
4672
199
                            if (JSON_UNLIKELY(not sax->end_array()))
4673
199
                            {
4674
0
                                return false;
4675
0
                            }
4676
199
                            break;
4677
199
                        }
4678
601
4679
601
                        // remember we are now inside an array
4680
601
                        states.push_back(true);
4681
402
4682
402
                        // parse values (no need to call get_token)
4683
402
                        continue;
4684
601
                    }
4685
601
4686
57.4k
                    case token_type::value_float:
4687
57.4k
                    {
4688
57.4k
                        const auto res = m_lexer.get_number_float();
4689
57.4k
4690
57.4k
                        if (JSON_UNLIKELY(not std::isfinite(res)))
4691
57.4k
                        {
4692
0
                            return sax->parse_error(m_lexer.get_position(),
4693
0
                                                    m_lexer.get_token_string(),
4694
0
                                                    out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'"));
4695
0
                        }
4696
57.4k
                        else
4697
57.4k
                        {
4698
57.4k
                            if (JSON_UNLIKELY(not sax->number_float(res, m_lexer.get_string())))
4699
57.4k
                            {
4700
0
                                return false;
4701
0
                            }
4702
57.4k
                            break;
4703
57.4k
                        }
4704
57.4k
                    }
4705
57.4k
4706
57.4k
                    case token_type::literal_false:
4707
0
                    {
4708
0
                        if (JSON_UNLIKELY(not sax->boolean(false)))
4709
0
                        {
4710
0
                            return false;
4711
0
                        }
4712
0
                        break;
4713
0
                    }
4714
0
4715
402
                    case token_type::literal_null:
4716
402
                    {
4717
402
                        if (JSON_UNLIKELY(not sax->null()))
4718
402
                        {
4719
0
                            return false;
4720
0
                        }
4721
402
                        break;
4722
402
                    }
4723
402
4724
602
                    case token_type::literal_true:
4725
602
                    {
4726
602
                        if (JSON_UNLIKELY(not sax->boolean(true)))
4727
602
                        {
4728
0
                            return false;
4729
0
                        }
4730
602
                        break;
4731
602
                    }
4732
602
4733
9.18k
                    case token_type::value_integer:
4734
9.18k
                    {
4735
9.18k
                        if (JSON_UNLIKELY(not sax->number_integer(m_lexer.get_number_integer())))
4736
9.18k
                        {
4737
0
                            return false;
4738
0
                        }
4739
9.18k
                        break;
4740
9.18k
                    }
4741
9.18k
4742
61.8k
                    case token_type::value_string:
4743
61.8k
                    {
4744
61.8k
                        if (JSON_UNLIKELY(not sax->string(m_lexer.get_string())))
4745
61.8k
                        {
4746
0
                            return false;
4747
0
                        }
4748
61.8k
                        break;
4749
61.8k
                    }
4750
61.8k
4751
77.0k
                    case token_type::value_unsigned:
4752
77.0k
                    {
4753
77.0k
                        if (JSON_UNLIKELY(not sax->number_unsigned(m_lexer.get_number_unsigned())))
4754
77.0k
                        {
4755
0
                            return false;
4756
0
                        }
4757
77.0k
                        break;
4758
77.0k
                    }
4759
77.0k
4760
77.0k
                    case token_type::parse_error:
4761
0
                    {
4762
0
                        // using "uninitialized" to avoid "expected" message
4763
0
                        return sax->parse_error(m_lexer.get_position(),
4764
0
                                                m_lexer.get_token_string(),
4765
0
                                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized)));
4766
77.0k
                    }
4767
77.0k
4768
77.0k
                    default: // the last token was unexpected
4769
1
                    {
4770
1
                        return sax->parse_error(m_lexer.get_position(),
4771
1
                                                m_lexer.get_token_string(),
4772
1
                                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value)));
4773
77.0k
                    }
4774
206k
                }
4775
257k
            }
4776
309k
            else
4777
309k
            {
4778
51.2k
                skip_to_state_evaluation = false;
4779
51.2k
            }
4780
309k
4781
309k
            // we reached this line after we successfully parsed a value
4782
309k
            if (states.empty())
4783
257k
            {
4784
834
                // empty stack: we reached the end of the hieararchy: done
4785
834
                return true;
4786
834
            }
4787
257k
            else
4788
257k
            {
4789
257k
                if (states.back())  // array
4790
257k
                {
4791
9.57k
                    // comma -> next value
4792
9.57k
                    if (get_token() == token_type::value_separator)
4793
9.57k
                    {
4794
9.17k
                        // parse a new value
4795
9.17k
                        get_token();
4796
9.17k
                        continue;
4797
9.17k
                    }
4798
9.57k
4799
9.57k
                    // closing ]
4800
9.57k
                    if (JSON_LIKELY(last_token == token_type::end_array))
4801
402
                    {
4802
402
                        if (JSON_UNLIKELY(not sax->end_array()))
4803
402
                        {
4804
0
                            return false;
4805
0
                        }
4806
402
4807
402
                        // We are done with this array. Before we can parse a
4808
402
                        // new value, we need to evaluate the new state first.
4809
402
                        // By setting skip_to_state_evaluation to false, we
4810
402
                        // are effectively jumping to the beginning of this if.
4811
402
                        assert(not states.empty());
4812
402
                        states.pop_back();
4813
402
                        skip_to_state_evaluation = true;
4814
402
                        continue;
4815
402
                    }
4816
402
                    else
4817
402
                    {
4818
0
                        return sax->parse_error(m_lexer.get_position(),
4819
0
                                                m_lexer.get_token_string(),
4820
0
                                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array)));
4821
0
                    }
4822
402
                }
4823
257k
                else  // object
4824
257k
                {
4825
247k
                    // comma -> next value
4826
247k
                    if (get_token() == token_type::value_separator)
4827
247k
                    {
4828
196k
                        // parse key
4829
196k
                        if (JSON_UNLIKELY(get_token() != token_type::value_string))
4830
196k
                        {
4831
0
                            return sax->parse_error(m_lexer.get_position(),
4832
0
                                                    m_lexer.get_token_string(),
4833
0
                                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string)));
4834
0
                        }
4835
196k
                        else
4836
196k
                        {
4837
196k
                            if (JSON_UNLIKELY(not sax->key(m_lexer.get_string())))
4838
196k
                            {
4839
0
                                return false;
4840
0
                            }
4841
196k
                        }
4842
196k
4843
196k
                        // parse separator (:)
4844
196k
                        if (JSON_UNLIKELY(get_token() != token_type::name_separator))
4845
196k
                        {
4846
0
                            return sax->parse_error(m_lexer.get_position(),
4847
0
                                                    m_lexer.get_token_string(),
4848
0
                                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator)));
4849
0
                        }
4850
196k
4851
196k
                        // parse values
4852
196k
                        get_token();
4853
196k
                        continue;
4854
196k
                    }
4855
247k
4856
247k
                    // closing }
4857
247k
                    if (JSON_LIKELY(last_token == token_type::end_object))
4858
50.8k
                    {
4859
50.8k
                        if (JSON_UNLIKELY(not sax->end_object()))
4860
50.8k
                        {
4861
0
                            return false;
4862
0
                        }
4863
50.8k
4864
50.8k
                        // We are done with this object. Before we can parse a
4865
50.8k
                        // new value, we need to evaluate the new state first.
4866
50.8k
                        // By setting skip_to_state_evaluation to false, we
4867
50.8k
                        // are effectively jumping to the beginning of this if.
4868
50.8k
                        assert(not states.empty());
4869
50.8k
                        states.pop_back();
4870
50.8k
                        skip_to_state_evaluation = true;
4871
50.8k
                        continue;
4872
50.8k
                    }
4873
50.8k
                    else
4874
50.8k
                    {
4875
0
                        return sax->parse_error(m_lexer.get_position(),
4876
0
                                                m_lexer.get_token_string(),
4877
0
                                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object)));
4878
0
                    }
4879
50.8k
                }
4880
257k
            }
4881
257k
        }
4882
835
    }
Unexecuted instantiation: _ZN8nlohmann6detail6parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEE18sax_parse_internalINS0_28json_sax_dom_callback_parserISC_EEEEbPT_
_ZN8nlohmann6detail6parserINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEE18sax_parse_internalINS0_19json_sax_dom_parserISC_EEEEbPT_
Line
Count
Source
4600
835
    {
4601
835
        // stack to remember the hieararchy of structured values we are parsing
4602
835
        // true = array; false = object
4603
835
        std::vector<bool> states;
4604
835
        // value to avoid a goto (see comment where set to true)
4605
835
        bool skip_to_state_evaluation = false;
4606
835
4607
309k
        while (true)
4608
309k
        {
4609
309k
            if (not skip_to_state_evaluation)
4610
309k
            {
4611
257k
                // invariant: get_token() was called before each iteration
4612
257k
                switch (last_token)
4613
206k
                {
4614
206k
                    case token_type::begin_object:
4615
50.8k
                    {
4616
50.8k
                        if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1))))
4617
50.8k
                        {
4618
0
                            return false;
4619
0
                        }
4620
50.8k
4621
50.8k
                        // closing } -> we are done
4622
50.8k
                        if (get_token() == token_type::end_object)
4623
50.8k
                        {
4624
0
                            if (JSON_UNLIKELY(not sax->end_object()))
4625
0
                            {
4626
0
                                return false;
4627
0
                            }
4628
0
                            break;
4629
0
                        }
4630
50.8k
4631
50.8k
                        // parse key
4632
50.8k
                        if (JSON_UNLIKELY(last_token != token_type::value_string))
4633
50.8k
                        {
4634
0
                            return sax->parse_error(m_lexer.get_position(),
4635
0
                                                    m_lexer.get_token_string(),
4636
0
                                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string)));
4637
0
                        }
4638
50.8k
                        else
4639
50.8k
                        {
4640
50.8k
                            if (JSON_UNLIKELY(not sax->key(m_lexer.get_string())))
4641
50.8k
                            {
4642
0
                                return false;
4643
0
                            }
4644
50.8k
                        }
4645
50.8k
4646
50.8k
                        // parse separator (:)
4647
50.8k
                        if (JSON_UNLIKELY(get_token() != token_type::name_separator))
4648
50.8k
                        {
4649
0
                            return sax->parse_error(m_lexer.get_position(),
4650
0
                                                    m_lexer.get_token_string(),
4651
0
                                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator)));
4652
0
                        }
4653
50.8k
4654
50.8k
                        // remember we are now inside an object
4655
50.8k
                        states.push_back(false);
4656
50.8k
4657
50.8k
                        // parse values
4658
50.8k
                        get_token();
4659
50.8k
                        continue;
4660
50.8k
                    }
4661
50.8k
4662
50.8k
                    case token_type::begin_array:
4663
601
                    {
4664
601
                        if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1))))
4665
601
                        {
4666
0
                            return false;
4667
0
                        }
4668
601
4669
601
                        // closing ] -> we are done
4670
601
                        if (get_token() == token_type::end_array)
4671
601
                        {
4672
199
                            if (JSON_UNLIKELY(not sax->end_array()))
4673
199
                            {
4674
0
                                return false;
4675
0
                            }
4676
199
                            break;
4677
199
                        }
4678
601
4679
601
                        // remember we are now inside an array
4680
601
                        states.push_back(true);
4681
402
4682
402
                        // parse values (no need to call get_token)
4683
402
                        continue;
4684
601
                    }
4685
601
4686
57.4k
                    case token_type::value_float:
4687
57.4k
                    {
4688
57.4k
                        const auto res = m_lexer.get_number_float();
4689
57.4k
4690
57.4k
                        if (JSON_UNLIKELY(not std::isfinite(res)))
4691
57.4k
                        {
4692
0
                            return sax->parse_error(m_lexer.get_position(),
4693
0
                                                    m_lexer.get_token_string(),
4694
0
                                                    out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'"));
4695
0
                        }
4696
57.4k
                        else
4697
57.4k
                        {
4698
57.4k
                            if (JSON_UNLIKELY(not sax->number_float(res, m_lexer.get_string())))
4699
57.4k
                            {
4700
0
                                return false;
4701
0
                            }
4702
57.4k
                            break;
4703
57.4k
                        }
4704
57.4k
                    }
4705
57.4k
4706
57.4k
                    case token_type::literal_false:
4707
0
                    {
4708
0
                        if (JSON_UNLIKELY(not sax->boolean(false)))
4709
0
                        {
4710
0
                            return false;
4711
0
                        }
4712
0
                        break;
4713
0
                    }
4714
0
4715
402
                    case token_type::literal_null:
4716
402
                    {
4717
402
                        if (JSON_UNLIKELY(not sax->null()))
4718
402
                        {
4719
0
                            return false;
4720
0
                        }
4721
402
                        break;
4722
402
                    }
4723
402
4724
602
                    case token_type::literal_true:
4725
602
                    {
4726
602
                        if (JSON_UNLIKELY(not sax->boolean(true)))
4727
602
                        {
4728
0
                            return false;
4729
0
                        }
4730
602
                        break;
4731
602
                    }
4732
602
4733
9.18k
                    case token_type::value_integer:
4734
9.18k
                    {
4735
9.18k
                        if (JSON_UNLIKELY(not sax->number_integer(m_lexer.get_number_integer())))
4736
9.18k
                        {
4737
0
                            return false;
4738
0
                        }
4739
9.18k
                        break;
4740
9.18k
                    }
4741
9.18k
4742
61.8k
                    case token_type::value_string:
4743
61.8k
                    {
4744
61.8k
                        if (JSON_UNLIKELY(not sax->string(m_lexer.get_string())))
4745
61.8k
                        {
4746
0
                            return false;
4747
0
                        }
4748
61.8k
                        break;
4749
61.8k
                    }
4750
61.8k
4751
77.0k
                    case token_type::value_unsigned:
4752
77.0k
                    {
4753
77.0k
                        if (JSON_UNLIKELY(not sax->number_unsigned(m_lexer.get_number_unsigned())))
4754
77.0k
                        {
4755
0
                            return false;
4756
0
                        }
4757
77.0k
                        break;
4758
77.0k
                    }
4759
77.0k
4760
77.0k
                    case token_type::parse_error:
4761
0
                    {
4762
0
                        // using "uninitialized" to avoid "expected" message
4763
0
                        return sax->parse_error(m_lexer.get_position(),
4764
0
                                                m_lexer.get_token_string(),
4765
0
                                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized)));
4766
77.0k
                    }
4767
77.0k
4768
77.0k
                    default: // the last token was unexpected
4769
1
                    {
4770
1
                        return sax->parse_error(m_lexer.get_position(),
4771
1
                                                m_lexer.get_token_string(),
4772
1
                                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value)));
4773
77.0k
                    }
4774
206k
                }
4775
257k
            }
4776
309k
            else
4777
309k
            {
4778
51.2k
                skip_to_state_evaluation = false;
4779
51.2k
            }
4780
309k
4781
309k
            // we reached this line after we successfully parsed a value
4782
309k
            if (states.empty())
4783
257k
            {
4784
834
                // empty stack: we reached the end of the hieararchy: done
4785
834
                return true;
4786
834
            }
4787
257k
            else
4788
257k
            {
4789
257k
                if (states.back())  // array
4790
257k
                {
4791
9.57k
                    // comma -> next value
4792
9.57k
                    if (get_token() == token_type::value_separator)
4793
9.57k
                    {
4794
9.17k
                        // parse a new value
4795
9.17k
                        get_token();
4796
9.17k
                        continue;
4797
9.17k
                    }
4798
9.57k
4799
9.57k
                    // closing ]
4800
9.57k
                    if (JSON_LIKELY(last_token == token_type::end_array))
4801
402
                    {
4802
402
                        if (JSON_UNLIKELY(not sax->end_array()))
4803
402
                        {
4804
0
                            return false;
4805
0
                        }
4806
402
4807
402
                        // We are done with this array. Before we can parse a
4808
402
                        // new value, we need to evaluate the new state first.
4809
402
                        // By setting skip_to_state_evaluation to false, we
4810
402
                        // are effectively jumping to the beginning of this if.
4811
402
                        assert(not states.empty());
4812
402
                        states.pop_back();
4813
402
                        skip_to_state_evaluation = true;
4814
402
                        continue;
4815
402
                    }
4816
402
                    else
4817
402
                    {
4818
0
                        return sax->parse_error(m_lexer.get_position(),
4819
0
                                                m_lexer.get_token_string(),
4820
0
                                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array)));
4821
0
                    }
4822
402
                }
4823
257k
                else  // object
4824
257k
                {
4825
247k
                    // comma -> next value
4826
247k
                    if (get_token() == token_type::value_separator)
4827
247k
                    {
4828
196k
                        // parse key
4829
196k
                        if (JSON_UNLIKELY(get_token() != token_type::value_string))
4830
196k
                        {
4831
0
                            return sax->parse_error(m_lexer.get_position(),
4832
0
                                                    m_lexer.get_token_string(),
4833
0
                                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string)));
4834
0
                        }
4835
196k
                        else
4836
196k
                        {
4837
196k
                            if (JSON_UNLIKELY(not sax->key(m_lexer.get_string())))
4838
196k
                            {
4839
0
                                return false;
4840
0
                            }
4841
196k
                        }
4842
196k
4843
196k
                        // parse separator (:)
4844
196k
                        if (JSON_UNLIKELY(get_token() != token_type::name_separator))
4845
196k
                        {
4846
0
                            return sax->parse_error(m_lexer.get_position(),
4847
0
                                                    m_lexer.get_token_string(),
4848
0
                                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator)));
4849
0
                        }
4850
196k
4851
196k
                        // parse values
4852
196k
                        get_token();
4853
196k
                        continue;
4854
196k
                    }
4855
247k
4856
247k
                    // closing }
4857
247k
                    if (JSON_LIKELY(last_token == token_type::end_object))
4858
50.8k
                    {
4859
50.8k
                        if (JSON_UNLIKELY(not sax->end_object()))
4860
50.8k
                        {
4861
0
                            return false;
4862
0
                        }
4863
50.8k
4864
50.8k
                        // We are done with this object. Before we can parse a
4865
50.8k
                        // new value, we need to evaluate the new state first.
4866
50.8k
                        // By setting skip_to_state_evaluation to false, we
4867
50.8k
                        // are effectively jumping to the beginning of this if.
4868
50.8k
                        assert(not states.empty());
4869
50.8k
                        states.pop_back();
4870
50.8k
                        skip_to_state_evaluation = true;
4871
50.8k
                        continue;
4872
50.8k
                    }
4873
50.8k
                    else
4874
50.8k
                    {
4875
0
                        return sax->parse_error(m_lexer.get_position(),
4876
0
                                                m_lexer.get_token_string(),
4877
0
                                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object)));
4878
0
                    }
4879
50.8k
                }
4880
257k
            }
4881
257k
        }
4882
835
    }
4883
4884
    /// get next token from lexer
4885
    token_type get_token()
4886
1.01M
    {
4887
1.01M
        return (last_token = m_lexer.scan());
4888
1.01M
    }
4889
4890
    std::string exception_message(const token_type expected)
4891
1
    {
4892
1
        std::string error_msg = "syntax error - ";
4893
1
        if (last_token == token_type::parse_error)
4894
1
        {
4895
0
            error_msg += std::string(m_lexer.get_error_message()) + "; last read: '" +
4896
0
                         m_lexer.get_token_string() + "'";
4897
0
        }
4898
1
        else
4899
1
        {
4900
1
            error_msg += "unexpected " + std::string(lexer_t::token_type_name(last_token));
4901
1
        }
4902
1
4903
1
        if (expected != token_type::uninitialized)
4904
1
        {
4905
1
            error_msg += "; expected " + std::string(lexer_t::token_type_name(expected));
4906
1
        }
4907
1
4908
1
        return error_msg;
4909
1
    }
4910
4911
  private:
4912
    /// callback function
4913
    const parser_callback_t callback = nullptr;
4914
    /// the type of the last read token
4915
    token_type last_token = token_type::uninitialized;
4916
    /// the lexer
4917
    lexer_t m_lexer;
4918
    /// whether to throw exceptions in case of errors
4919
    const bool allow_exceptions = true;
4920
};
4921
}
4922
}
4923
4924
// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
4925
4926
4927
#include <cstddef> // ptrdiff_t
4928
#include <limits>  // numeric_limits
4929
4930
namespace nlohmann
4931
{
4932
namespace detail
4933
{
4934
/*
4935
@brief an iterator for primitive JSON types
4936
4937
This class models an iterator for primitive JSON types (boolean, number,
4938
string). It's only purpose is to allow the iterator/const_iterator classes
4939
to "iterate" over primitive values. Internally, the iterator is modeled by
4940
a `difference_type` variable. Value begin_value (`0`) models the begin,
4941
end_value (`1`) models past the end.
4942
*/
4943
class primitive_iterator_t
4944
{
4945
  private:
4946
    using difference_type = std::ptrdiff_t;
4947
    static constexpr difference_type begin_value = 0;
4948
    static constexpr difference_type end_value = begin_value + 1;
4949
4950
    /// iterator as signed integer type
4951
    difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
4952
4953
  public:
4954
    constexpr difference_type get_value() const noexcept
4955
0
    {
4956
0
        return m_it;
4957
0
    }
4958
4959
    /// set iterator to a defined beginning
4960
    void set_begin() noexcept
4961
0
    {
4962
0
        m_it = begin_value;
4963
0
    }
4964
4965
    /// set iterator to a defined past the end
4966
    void set_end() noexcept
4967
2
    {
4968
2
        m_it = end_value;
4969
2
    }
4970
4971
    /// return whether the iterator can be dereferenced
4972
    constexpr bool is_begin() const noexcept
4973
0
    {
4974
0
        return m_it == begin_value;
4975
0
    }
4976
4977
    /// return whether the iterator is at end
4978
    constexpr bool is_end() const noexcept
4979
0
    {
4980
0
        return m_it == end_value;
4981
0
    }
4982
4983
    friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
4984
1
    {
4985
1
        return lhs.m_it == rhs.m_it;
4986
1
    }
4987
4988
    friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
4989
    {
4990
        return lhs.m_it < rhs.m_it;
4991
    }
4992
4993
    primitive_iterator_t operator+(difference_type n) noexcept
4994
0
    {
4995
0
        auto result = *this;
4996
0
        result += n;
4997
0
        return result;
4998
0
    }
4999
5000
    friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
5001
    {
5002
        return lhs.m_it - rhs.m_it;
5003
    }
5004
5005
    primitive_iterator_t& operator++() noexcept
5006
0
    {
5007
0
        ++m_it;
5008
0
        return *this;
5009
0
    }
5010
5011
    primitive_iterator_t const operator++(int) noexcept
5012
0
    {
5013
0
        auto result = *this;
5014
0
        ++m_it;
5015
0
        return result;
5016
0
    }
5017
5018
    primitive_iterator_t& operator--() noexcept
5019
0
    {
5020
0
        --m_it;
5021
0
        return *this;
5022
0
    }
5023
5024
    primitive_iterator_t const operator--(int) noexcept
5025
0
    {
5026
0
        auto result = *this;
5027
0
        --m_it;
5028
0
        return result;
5029
0
    }
5030
5031
    primitive_iterator_t& operator+=(difference_type n) noexcept
5032
0
    {
5033
0
        m_it += n;
5034
0
        return *this;
5035
0
    }
5036
5037
    primitive_iterator_t& operator-=(difference_type n) noexcept
5038
0
    {
5039
0
        m_it -= n;
5040
0
        return *this;
5041
0
    }
5042
};
5043
}
5044
}
5045
5046
// #include <nlohmann/detail/iterators/internal_iterator.hpp>
5047
5048
5049
// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
5050
5051
5052
namespace nlohmann
5053
{
5054
namespace detail
5055
{
5056
/*!
5057
@brief an iterator value
5058
5059
@note This structure could easily be a union, but MSVC currently does not allow
5060
unions members with complex constructors, see https://github.com/nlohmann/json/pull/105.
5061
*/
5062
template<typename BasicJsonType> struct internal_iterator
5063
{
5064
    /// iterator for JSON objects
5065
    typename BasicJsonType::object_t::iterator object_iterator {};
5066
    /// iterator for JSON arrays
5067
    typename BasicJsonType::array_t::iterator array_iterator {};
5068
    /// generic iterator for all other types
5069
    primitive_iterator_t primitive_iterator {};
5070
};
5071
}
5072
}
5073
5074
// #include <nlohmann/detail/iterators/iter_impl.hpp>
5075
5076
5077
#include <ciso646> // not
5078
#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
5079
#include <type_traits> // conditional, is_const, remove_const
5080
5081
// #include <nlohmann/detail/exceptions.hpp>
5082
5083
// #include <nlohmann/detail/iterators/internal_iterator.hpp>
5084
5085
// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
5086
5087
// #include <nlohmann/detail/macro_scope.hpp>
5088
5089
// #include <nlohmann/detail/meta/cpp_future.hpp>
5090
5091
// #include <nlohmann/detail/value_t.hpp>
5092
5093
5094
namespace nlohmann
5095
{
5096
namespace detail
5097
{
5098
// forward declare, to be able to friend it later on
5099
template<typename IteratorType> class iteration_proxy;
5100
5101
/*!
5102
@brief a template for a bidirectional iterator for the @ref basic_json class
5103
5104
This class implements a both iterators (iterator and const_iterator) for the
5105
@ref basic_json class.
5106
5107
@note An iterator is called *initialized* when a pointer to a JSON value has
5108
      been set (e.g., by a constructor or a copy assignment). If the iterator is
5109
      default-constructed, it is *uninitialized* and most methods are undefined.
5110
      **The library uses assertions to detect calls on uninitialized iterators.**
5111
5112
@requirement The class satisfies the following concept requirements:
5113
-
5114
[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
5115
  The iterator that can be moved can be moved in both directions (i.e.
5116
  incremented and decremented).
5117
5118
@since version 1.0.0, simplified in version 2.0.9, change to bidirectional
5119
       iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593)
5120
*/
5121
template<typename BasicJsonType>
5122
class iter_impl
5123
{
5124
    /// allow basic_json to access private members
5125
    friend iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
5126
    friend BasicJsonType;
5127
    friend iteration_proxy<iter_impl>;
5128
5129
    using object_t = typename BasicJsonType::object_t;
5130
    using array_t = typename BasicJsonType::array_t;
5131
    // make sure BasicJsonType is basic_json or const basic_json
5132
    static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value,
5133
                  "iter_impl only accepts (const) basic_json");
5134
5135
  public:
5136
5137
    /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
5138
    /// The C++ Standard has never required user-defined iterators to derive from std::iterator.
5139
    /// A user-defined iterator should provide publicly accessible typedefs named
5140
    /// iterator_category, value_type, difference_type, pointer, and reference.
5141
    /// Note that value_type is required to be non-const, even for constant iterators.
5142
    using iterator_category = std::bidirectional_iterator_tag;
5143
5144
    /// the type of the values when the iterator is dereferenced
5145
    using value_type = typename BasicJsonType::value_type;
5146
    /// a type to represent differences between iterators
5147
    using difference_type = typename BasicJsonType::difference_type;
5148
    /// defines a pointer to the type iterated over (value_type)
5149
    using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
5150
          typename BasicJsonType::const_pointer,
5151
          typename BasicJsonType::pointer>::type;
5152
    /// defines a reference to the type iterated over (value_type)
5153
    using reference =
5154
        typename std::conditional<std::is_const<BasicJsonType>::value,
5155
        typename BasicJsonType::const_reference,
5156
        typename BasicJsonType::reference>::type;
5157
5158
    /// default constructor
5159
    iter_impl() = default;
5160
5161
    /*!
5162
    @brief constructor for a given JSON instance
5163
    @param[in] object  pointer to a JSON object for this iterator
5164
    @pre object != nullptr
5165
    @post The iterator is initialized; i.e. `m_object != nullptr`.
5166
    */
5167
    explicit iter_impl(pointer object) noexcept : m_object(object)
5168
2.57k
    {
5169
2.57k
        assert(m_object != nullptr);
5170
2.57k
5171
2.57k
        switch (m_object->m_type)
5172
2.57k
        {
5173
2.57k
            case value_t::object:
5174
2.55k
            {
5175
2.55k
                m_it.object_iterator = typename object_t::iterator();
5176
2.55k
                break;
5177
2.55k
            }
5178
2.55k
5179
2.55k
            case value_t::array:
5180
16
            {
5181
16
                m_it.array_iterator = typename array_t::iterator();
5182
16
                break;
5183
2.55k
            }
5184
2.55k
5185
2.55k
            default:
5186
2
            {
5187
2
                m_it.primitive_iterator = primitive_iterator_t();
5188
2
                break;
5189
2.55k
            }
5190
2.57k
        }
5191
2.57k
    }
5192
5193
    /*!
5194
    @note The conventional copy constructor and copy assignment are implicitly
5195
          defined. Combined with the following converting constructor and
5196
          assignment, they support: (1) copy from iterator to iterator, (2)
5197
          copy from const iterator to const iterator, and (3) conversion from
5198
          iterator to const iterator. However conversion from const iterator
5199
          to iterator is not defined.
5200
    */
5201
5202
    /*!
5203
    @brief converting constructor
5204
    @param[in] other  non-const iterator to copy from
5205
    @note It is not checked whether @a other is initialized.
5206
    */
5207
    iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
5208
0
        : m_object(other.m_object), m_it(other.m_it) {}
5209
5210
    /*!
5211
    @brief converting assignment
5212
    @param[in,out] other  non-const iterator to copy from
5213
    @return const/non-const iterator
5214
    @note It is not checked whether @a other is initialized.
5215
    */
5216
    iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
5217
    {
5218
        m_object = other.m_object;
5219
        m_it = other.m_it;
5220
        return *this;
5221
    }
5222
5223
  private:
5224
    /*!
5225
    @brief set the iterator to the first value
5226
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5227
    */
5228
    void set_begin() noexcept
5229
590
    {
5230
590
        assert(m_object != nullptr);
5231
590
5232
590
        switch (m_object->m_type)
5233
590
        {
5234
590
            case value_t::object:
5235
582
            {
5236
582
                m_it.object_iterator = m_object->m_value.object->begin();
5237
582
                break;
5238
582
            }
5239
582
5240
582
            case value_t::array:
5241
8
            {
5242
8
                m_it.array_iterator = m_object->m_value.array->begin();
5243
8
                break;
5244
582
            }
5245
582
5246
582
            case value_t::null:
5247
0
            {
5248
0
                // set to end so begin()==end() is true: null is empty
5249
0
                m_it.primitive_iterator.set_end();
5250
0
                break;
5251
582
            }
5252
582
5253
582
            default:
5254
0
            {
5255
0
                m_it.primitive_iterator.set_begin();
5256
0
                break;
5257
582
            }
5258
590
        }
5259
590
    }
5260
5261
    /*!
5262
    @brief set the iterator past the last value
5263
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5264
    */
5265
    void set_end() noexcept
5266
1.98k
    {
5267
1.98k
        assert(m_object != nullptr);
5268
1.98k
5269
1.98k
        switch (m_object->m_type)
5270
1.98k
        {
5271
1.98k
            case value_t::object:
5272
1.97k
            {
5273
1.97k
                m_it.object_iterator = m_object->m_value.object->end();
5274
1.97k
                break;
5275
1.97k
            }
5276
1.97k
5277
1.97k
            case value_t::array:
5278
8
            {
5279
8
                m_it.array_iterator = m_object->m_value.array->end();
5280
8
                break;
5281
1.97k
            }
5282
1.97k
5283
1.97k
            default:
5284
2
            {
5285
2
                m_it.primitive_iterator.set_end();
5286
2
                break;
5287
1.97k
            }
5288
1.98k
        }
5289
1.98k
    }
5290
5291
  public:
5292
    /*!
5293
    @brief return a reference to the value pointed to by the iterator
5294
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5295
    */
5296
    reference operator*() const
5297
1.51k
    {
5298
1.51k
        assert(m_object != nullptr);
5299
1.51k
5300
1.51k
        switch (m_object->m_type)
5301
0
        {
5302
1.36k
            case value_t::object:
5303
1.36k
            {
5304
1.36k
                assert(m_it.object_iterator != m_object->m_value.object->end());
5305
1.36k
                return m_it.object_iterator->second;
5306
1.36k
            }
5307
1.36k
5308
1.36k
            case value_t::array:
5309
146
            {
5310
146
                assert(m_it.array_iterator != m_object->m_value.array->end());
5311
146
                return *m_it.array_iterator;
5312
1.36k
            }
5313
1.36k
5314
1.36k
            case value_t::null:
5315
0
                JSON_THROW(invalid_iterator::create(214, "cannot get value"));
5316
1.36k
5317
1.36k
            default:
5318
0
            {
5319
0
                if (JSON_LIKELY(m_it.primitive_iterator.is_begin()))
5320
0
                {
5321
0
                    return *m_object;
5322
0
                }
5323
0
5324
0
                JSON_THROW(invalid_iterator::create(214, "cannot get value"));
5325
0
            }
5326
0
        }
5327
1.51k
    }
5328
5329
    /*!
5330
    @brief dereference the iterator
5331
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5332
    */
5333
    pointer operator->() const
5334
0
    {
5335
0
        assert(m_object != nullptr);
5336
0
5337
0
        switch (m_object->m_type)
5338
0
        {
5339
0
            case value_t::object:
5340
0
            {
5341
0
                assert(m_it.object_iterator != m_object->m_value.object->end());
5342
0
                return &(m_it.object_iterator->second);
5343
0
            }
5344
0
5345
0
            case value_t::array:
5346
0
            {
5347
0
                assert(m_it.array_iterator != m_object->m_value.array->end());
5348
0
                return &*m_it.array_iterator;
5349
0
            }
5350
0
5351
0
            default:
5352
0
            {
5353
0
                if (JSON_LIKELY(m_it.primitive_iterator.is_begin()))
5354
0
                {
5355
0
                    return m_object;
5356
0
                }
5357
0
5358
0
                JSON_THROW(invalid_iterator::create(214, "cannot get value"));
5359
0
            }
5360
0
        }
5361
0
    }
5362
5363
    /*!
5364
    @brief post-increment (it++)
5365
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5366
    */
5367
    iter_impl const operator++(int)
5368
    {
5369
        auto result = *this;
5370
        ++(*this);
5371
        return result;
5372
    }
5373
5374
    /*!
5375
    @brief pre-increment (++it)
5376
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5377
    */
5378
    iter_impl& operator++()
5379
1.50k
    {
5380
1.50k
        assert(m_object != nullptr);
5381
1.50k
5382
1.50k
        switch (m_object->m_type)
5383
1.50k
        {
5384
1.50k
            case value_t::object:
5385
1.36k
            {
5386
1.36k
                std::advance(m_it.object_iterator, 1);
5387
1.36k
                break;
5388
1.36k
            }
5389
1.36k
5390
1.36k
            case value_t::array:
5391
146
            {
5392
146
                std::advance(m_it.array_iterator, 1);
5393
146
                break;
5394
1.36k
            }
5395
1.36k
5396
1.36k
            default:
5397
0
            {
5398
0
                ++m_it.primitive_iterator;
5399
0
                break;
5400
1.36k
            }
5401
1.50k
        }
5402
1.50k
5403
1.50k
        return *this;
5404
1.50k
    }
5405
5406
    /*!
5407
    @brief post-decrement (it--)
5408
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5409
    */
5410
    iter_impl const operator--(int)
5411
    {
5412
        auto result = *this;
5413
        --(*this);
5414
        return result;
5415
    }
5416
5417
    /*!
5418
    @brief pre-decrement (--it)
5419
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5420
    */
5421
    iter_impl& operator--()
5422
    {
5423
        assert(m_object != nullptr);
5424
5425
        switch (m_object->m_type)
5426
        {
5427
            case value_t::object:
5428
            {
5429
                std::advance(m_it.object_iterator, -1);
5430
                break;
5431
            }
5432
5433
            case value_t::array:
5434
            {
5435
                std::advance(m_it.array_iterator, -1);
5436
                break;
5437
            }
5438
5439
            default:
5440
            {
5441
                --m_it.primitive_iterator;
5442
                break;
5443
            }
5444
        }
5445
5446
        return *this;
5447
    }
5448
5449
    /*!
5450
    @brief  comparison: equal
5451
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5452
    */
5453
    bool operator==(const iter_impl& other) const
5454
2.11k
    {
5455
2.11k
        // if objects are not the same, the comparison is undefined
5456
2.11k
        if (JSON_UNLIKELY(m_object != other.m_object))
5457
2.11k
        {
5458
0
            JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
5459
0
        }
5460
2.11k
5461
2.11k
        assert(m_object != nullptr);
5462
2.11k
5463
2.11k
        switch (m_object->m_type)
5464
0
        {
5465
1.95k
            case value_t::object:
5466
1.95k
                return (m_it.object_iterator == other.m_it.object_iterator);
5467
1.95k
5468
1.95k
            case value_t::array:
5469
154
                return (m_it.array_iterator == other.m_it.array_iterator);
5470
1.95k
5471
1.95k
            default:
5472
1
                return (m_it.primitive_iterator == other.m_it.primitive_iterator);
5473
0
        }
5474
2.11k
    }
5475
5476
    /*!
5477
    @brief  comparison: not equal
5478
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5479
    */
5480
    bool operator!=(const iter_impl& other) const
5481
2.11k
    {
5482
2.11k
        return not operator==(other);
5483
2.11k
    }
5484
5485
    /*!
5486
    @brief  comparison: smaller
5487
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5488
    */
5489
    bool operator<(const iter_impl& other) const
5490
    {
5491
        // if objects are not the same, the comparison is undefined
5492
        if (JSON_UNLIKELY(m_object != other.m_object))
5493
        {
5494
            JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
5495
        }
5496
5497
        assert(m_object != nullptr);
5498
5499
        switch (m_object->m_type)
5500
        {
5501
            case value_t::object:
5502
                JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators"));
5503
5504
            case value_t::array:
5505
                return (m_it.array_iterator < other.m_it.array_iterator);
5506
5507
            default:
5508
                return (m_it.primitive_iterator < other.m_it.primitive_iterator);
5509
        }
5510
    }
5511
5512
    /*!
5513
    @brief  comparison: less than or equal
5514
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5515
    */
5516
    bool operator<=(const iter_impl& other) const
5517
    {
5518
        return not other.operator < (*this);
5519
    }
5520
5521
    /*!
5522
    @brief  comparison: greater than
5523
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5524
    */
5525
    bool operator>(const iter_impl& other) const
5526
    {
5527
        return not operator<=(other);
5528
    }
5529
5530
    /*!
5531
    @brief  comparison: greater than or equal
5532
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5533
    */
5534
    bool operator>=(const iter_impl& other) const
5535
    {
5536
        return not operator<(other);
5537
    }
5538
5539
    /*!
5540
    @brief  add to iterator
5541
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5542
    */
5543
    iter_impl& operator+=(difference_type i)
5544
    {
5545
        assert(m_object != nullptr);
5546
5547
        switch (m_object->m_type)
5548
        {
5549
            case value_t::object:
5550
                JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
5551
5552
            case value_t::array:
5553
            {
5554
                std::advance(m_it.array_iterator, i);
5555
                break;
5556
            }
5557
5558
            default:
5559
            {
5560
                m_it.primitive_iterator += i;
5561
                break;
5562
            }
5563
        }
5564
5565
        return *this;
5566
    }
5567
5568
    /*!
5569
    @brief  subtract from iterator
5570
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5571
    */
5572
    iter_impl& operator-=(difference_type i)
5573
    {
5574
        return operator+=(-i);
5575
    }
5576
5577
    /*!
5578
    @brief  add to iterator
5579
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5580
    */
5581
    iter_impl operator+(difference_type i) const
5582
    {
5583
        auto result = *this;
5584
        result += i;
5585
        return result;
5586
    }
5587
5588
    /*!
5589
    @brief  addition of distance and iterator
5590
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5591
    */
5592
    friend iter_impl operator+(difference_type i, const iter_impl& it)
5593
    {
5594
        auto result = it;
5595
        result += i;
5596
        return result;
5597
    }
5598
5599
    /*!
5600
    @brief  subtract from iterator
5601
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5602
    */
5603
    iter_impl operator-(difference_type i) const
5604
    {
5605
        auto result = *this;
5606
        result -= i;
5607
        return result;
5608
    }
5609
5610
    /*!
5611
    @brief  return difference
5612
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5613
    */
5614
    difference_type operator-(const iter_impl& other) const
5615
    {
5616
        assert(m_object != nullptr);
5617
5618
        switch (m_object->m_type)
5619
        {
5620
            case value_t::object:
5621
                JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
5622
5623
            case value_t::array:
5624
                return m_it.array_iterator - other.m_it.array_iterator;
5625
5626
            default:
5627
                return m_it.primitive_iterator - other.m_it.primitive_iterator;
5628
        }
5629
    }
5630
5631
    /*!
5632
    @brief  access to successor
5633
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5634
    */
5635
    reference operator[](difference_type n) const
5636
    {
5637
        assert(m_object != nullptr);
5638
5639
        switch (m_object->m_type)
5640
        {
5641
            case value_t::object:
5642
                JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators"));
5643
5644
            case value_t::array:
5645
                return *std::next(m_it.array_iterator, n);
5646
5647
            case value_t::null:
5648
                JSON_THROW(invalid_iterator::create(214, "cannot get value"));
5649
5650
            default:
5651
            {
5652
                if (JSON_LIKELY(m_it.primitive_iterator.get_value() == -n))
5653
                {
5654
                    return *m_object;
5655
                }
5656
5657
                JSON_THROW(invalid_iterator::create(214, "cannot get value"));
5658
            }
5659
        }
5660
    }
5661
5662
    /*!
5663
    @brief  return the key of an object iterator
5664
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5665
    */
5666
    const typename object_t::key_type& key() const
5667
0
    {
5668
0
        assert(m_object != nullptr);
5669
0
5670
0
        if (JSON_LIKELY(m_object->is_object()))
5671
0
        {
5672
0
            return m_it.object_iterator->first;
5673
0
        }
5674
0
5675
0
        JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators"));
5676
0
    }
5677
5678
    /*!
5679
    @brief  return the value of an iterator
5680
    @pre The iterator is initialized; i.e. `m_object != nullptr`.
5681
    */
5682
    reference value() const
5683
1.36k
    {
5684
1.36k
        return operator*();
5685
1.36k
    }
5686
5687
  private:
5688
    /// associated JSON instance
5689
    pointer m_object = nullptr;
5690
    /// the actual iterator of the associated instance
5691
    internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it;
5692
};
5693
}
5694
}
5695
5696
// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
5697
5698
// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
5699
5700
5701
#include <cstddef> // ptrdiff_t
5702
#include <iterator> // reverse_iterator
5703
#include <utility> // declval
5704
5705
namespace nlohmann
5706
{
5707
namespace detail
5708
{
5709
//////////////////////
5710
// reverse_iterator //
5711
//////////////////////
5712
5713
/*!
5714
@brief a template for a reverse iterator class
5715
5716
@tparam Base the base iterator type to reverse. Valid types are @ref
5717
iterator (to create @ref reverse_iterator) and @ref const_iterator (to
5718
create @ref const_reverse_iterator).
5719
5720
@requirement The class satisfies the following concept requirements:
5721
-
5722
[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
5723
  The iterator that can be moved can be moved in both directions (i.e.
5724
  incremented and decremented).
5725
- [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator):
5726
  It is possible to write to the pointed-to element (only if @a Base is
5727
  @ref iterator).
5728
5729
@since version 1.0.0
5730
*/
5731
template<typename Base>
5732
class json_reverse_iterator : public std::reverse_iterator<Base>
5733
{
5734
  public:
5735
    using difference_type = std::ptrdiff_t;
5736
    /// shortcut to the reverse iterator adapter
5737
    using base_iterator = std::reverse_iterator<Base>;
5738
    /// the reference type for the pointed-to element
5739
    using reference = typename Base::reference;
5740
5741
    /// create reverse iterator from iterator
5742
    explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
5743
        : base_iterator(it) {}
5744
5745
    /// create reverse iterator from base class
5746
    explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
5747
5748
    /// post-increment (it++)
5749
    json_reverse_iterator const operator++(int)
5750
    {
5751
        return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
5752
    }
5753
5754
    /// pre-increment (++it)
5755
    json_reverse_iterator& operator++()
5756
    {
5757
        return static_cast<json_reverse_iterator&>(base_iterator::operator++());
5758
    }
5759
5760
    /// post-decrement (it--)
5761
    json_reverse_iterator const operator--(int)
5762
    {
5763
        return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
5764
    }
5765
5766
    /// pre-decrement (--it)
5767
    json_reverse_iterator& operator--()
5768
    {
5769
        return static_cast<json_reverse_iterator&>(base_iterator::operator--());
5770
    }
5771
5772
    /// add to iterator
5773
    json_reverse_iterator& operator+=(difference_type i)
5774
    {
5775
        return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
5776
    }
5777
5778
    /// add to iterator
5779
    json_reverse_iterator operator+(difference_type i) const
5780
    {
5781
        return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
5782
    }
5783
5784
    /// subtract from iterator
5785
    json_reverse_iterator operator-(difference_type i) const
5786
    {
5787
        return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
5788
    }
5789
5790
    /// return difference
5791
    difference_type operator-(const json_reverse_iterator& other) const
5792
    {
5793
        return base_iterator(*this) - base_iterator(other);
5794
    }
5795
5796
    /// access to successor
5797
    reference operator[](difference_type n) const
5798
    {
5799
        return *(this->operator+(n));
5800
    }
5801
5802
    /// return the key of an object iterator
5803
    auto key() const -> decltype(std::declval<Base>().key())
5804
    {
5805
        auto it = --this->base();
5806
        return it.key();
5807
    }
5808
5809
    /// return the value of an iterator
5810
    reference value() const
5811
    {
5812
        auto it = --this->base();
5813
        return it.operator * ();
5814
    }
5815
};
5816
}
5817
}
5818
5819
// #include <nlohmann/detail/output/output_adapters.hpp>
5820
5821
5822
#include <algorithm> // copy
5823
#include <cstddef> // size_t
5824
#include <ios> // streamsize
5825
#include <iterator> // back_inserter
5826
#include <memory> // shared_ptr, make_shared
5827
#include <ostream> // basic_ostream
5828
#include <string> // basic_string
5829
#include <vector> // vector
5830
5831
namespace nlohmann
5832
{
5833
namespace detail
5834
{
5835
/// abstract output adapter interface
5836
template<typename CharType> struct output_adapter_protocol
5837
{
5838
    virtual void write_character(CharType c) = 0;
5839
    virtual void write_characters(const CharType* s, std::size_t length) = 0;
5840
122
    virtual ~output_adapter_protocol() = default;
5841
};
5842
5843
/// a type to simplify interfaces
5844
template<typename CharType>
5845
using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
5846
5847
/// output adapter for byte vectors
5848
template<typename CharType>
5849
class output_vector_adapter : public output_adapter_protocol<CharType>
5850
{
5851
  public:
5852
    explicit output_vector_adapter(std::vector<CharType>& vec) : v(vec) {}
5853
5854
    void write_character(CharType c) override
5855
    {
5856
        v.push_back(c);
5857
    }
5858
5859
    void write_characters(const CharType* s, std::size_t length) override
5860
    {
5861
        std::copy(s, s + length, std::back_inserter(v));
5862
    }
5863
5864
  private:
5865
    std::vector<CharType>& v;
5866
};
5867
5868
/// output adapter for output streams
5869
template<typename CharType>
5870
class output_stream_adapter : public output_adapter_protocol<CharType>
5871
{
5872
  public:
5873
105
    explicit output_stream_adapter(std::basic_ostream<CharType>& s) : stream(s) {}
5874
5875
    void write_character(CharType c) override
5876
7.48k
    {
5877
7.48k
        stream.put(c);
5878
7.48k
    }
5879
5880
    void write_characters(const CharType* s, std::size_t length) override
5881
10.3k
    {
5882
10.3k
        stream.write(s, static_cast<std::streamsize>(length));
5883
10.3k
    }
5884
5885
  private:
5886
    std::basic_ostream<CharType>& stream;
5887
};
5888
5889
/// output adapter for basic_string
5890
template<typename CharType, typename StringType = std::basic_string<CharType>>
5891
class output_string_adapter : public output_adapter_protocol<CharType>
5892
{
5893
  public:
5894
17
    explicit output_string_adapter(StringType& s) : str(s) {}
5895
5896
    void write_character(CharType c) override
5897
111
    {
5898
111
        str.push_back(c);
5899
111
    }
5900
5901
    void write_characters(const CharType* s, std::size_t length) override
5902
241
    {
5903
241
        str.append(s, length);
5904
241
    }
5905
5906
  private:
5907
    StringType& str;
5908
};
5909
5910
template<typename CharType, typename StringType = std::basic_string<CharType>>
5911
class output_adapter
5912
{
5913
  public:
5914
    output_adapter(std::vector<CharType>& vec)
5915
        : oa(std::make_shared<output_vector_adapter<CharType>>(vec)) {}
5916
5917
    output_adapter(std::basic_ostream<CharType>& s)
5918
105
        : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
5919
5920
    output_adapter(StringType& s)
5921
17
        : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
5922
5923
    operator output_adapter_t<CharType>()
5924
122
    {
5925
122
        return oa;
5926
122
    }
5927
5928
  private:
5929
    output_adapter_t<CharType> oa = nullptr;
5930
};
5931
}
5932
}
5933
5934
// #include <nlohmann/detail/input/binary_reader.hpp>
5935
5936
5937
#include <algorithm> // generate_n
5938
#include <array> // array
5939
#include <cassert> // assert
5940
#include <cmath> // ldexp
5941
#include <cstddef> // size_t
5942
#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
5943
#include <cstdio> // snprintf
5944
#include <cstring> // memcpy
5945
#include <iterator> // back_inserter
5946
#include <limits> // numeric_limits
5947
#include <string> // char_traits, string
5948
#include <utility> // make_pair, move
5949
5950
// #include <nlohmann/detail/input/input_adapters.hpp>
5951
5952
// #include <nlohmann/detail/input/json_sax.hpp>
5953
5954
// #include <nlohmann/detail/exceptions.hpp>
5955
5956
// #include <nlohmann/detail/macro_scope.hpp>
5957
5958
// #include <nlohmann/detail/meta/is_sax.hpp>
5959
5960
// #include <nlohmann/detail/value_t.hpp>
5961
5962
5963
namespace nlohmann
5964
{
5965
namespace detail
5966
{
5967
///////////////////
5968
// binary reader //
5969
///////////////////
5970
5971
/*!
5972
@brief deserialization of CBOR, MessagePack, and UBJSON values
5973
*/
5974
template<typename BasicJsonType, typename SAX = json_sax_dom_parser<BasicJsonType>>
5975
class binary_reader
5976
{
5977
    using number_integer_t = typename BasicJsonType::number_integer_t;
5978
    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5979
    using number_float_t = typename BasicJsonType::number_float_t;
5980
    using string_t = typename BasicJsonType::string_t;
5981
    using json_sax_t = SAX;
5982
5983
  public:
5984
    /*!
5985
    @brief create a binary reader
5986
5987
    @param[in] adapter  input adapter to read from
5988
    */
5989
    explicit binary_reader(input_adapter_t adapter) : ia(std::move(adapter))
5990
    {
5991
        (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
5992
        assert(ia);
5993
    }
5994
5995
    /*!
5996
    @param[in] format  the binary format to parse
5997
    @param[in] sax_    a SAX event processor
5998
    @param[in] strict  whether to expect the input to be consumed completed
5999
6000
    @return
6001
    */
6002
    bool sax_parse(const input_format_t format,
6003
                   json_sax_t* sax_,
6004
                   const bool strict = true)
6005
    {
6006
        sax = sax_;
6007
        bool result = false;
6008
6009
        switch (format)
6010
        {
6011
            case input_format_t::cbor:
6012
                result = parse_cbor_internal();
6013
                break;
6014
6015
            case input_format_t::msgpack:
6016
                result = parse_msgpack_internal();
6017
                break;
6018
6019
            case input_format_t::ubjson:
6020
                result = parse_ubjson_internal();
6021
                break;
6022
6023
            // LCOV_EXCL_START
6024
            default:
6025
                assert(false);
6026
                // LCOV_EXCL_STOP
6027
        }
6028
6029
        // strict mode: next byte must be EOF
6030
        if (result and strict)
6031
        {
6032
            if (format == input_format_t::ubjson)
6033
            {
6034
                get_ignore_noop();
6035
            }
6036
            else
6037
            {
6038
                get();
6039
            }
6040
6041
            if (JSON_UNLIKELY(current != std::char_traits<char>::eof()))
6042
            {
6043
                return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read, "expected end of input"));
6044
            }
6045
        }
6046
6047
        return result;
6048
    }
6049
6050
    /*!
6051
    @brief determine system byte order
6052
6053
    @return true if and only if system's byte order is little endian
6054
6055
    @note from http://stackoverflow.com/a/1001328/266378
6056
    */
6057
    static constexpr bool little_endianess(int num = 1) noexcept
6058
    {
6059
        return (*reinterpret_cast<char*>(&num) == 1);
6060
    }
6061
6062
  private:
6063
    /*!
6064
    @param[in] get_char  whether a new character should be retrieved from the
6065
                         input (true, default) or whether the last read
6066
                         character should be considered instead
6067
6068
    @return whether a valid CBOR value was passed to the SAX parser
6069
    */
6070
    bool parse_cbor_internal(const bool get_char = true)
6071
    {
6072
        switch (get_char ? get() : current)
6073
        {
6074
            // EOF
6075
            case std::char_traits<char>::eof():
6076
                return unexpect_eof();
6077
6078
            // Integer 0x00..0x17 (0..23)
6079
            case 0x00:
6080
            case 0x01:
6081
            case 0x02:
6082
            case 0x03:
6083
            case 0x04:
6084
            case 0x05:
6085
            case 0x06:
6086
            case 0x07:
6087
            case 0x08:
6088
            case 0x09:
6089
            case 0x0A:
6090
            case 0x0B:
6091
            case 0x0C:
6092
            case 0x0D:
6093
            case 0x0E:
6094
            case 0x0F:
6095
            case 0x10:
6096
            case 0x11:
6097
            case 0x12:
6098
            case 0x13:
6099
            case 0x14:
6100
            case 0x15:
6101
            case 0x16:
6102
            case 0x17:
6103
                return sax->number_unsigned(static_cast<number_unsigned_t>(current));
6104
6105
            case 0x18: // Unsigned integer (one-byte uint8_t follows)
6106
            {
6107
                uint8_t number;
6108
                return get_number(number) and sax->number_unsigned(number);
6109
            }
6110
6111
            case 0x19: // Unsigned integer (two-byte uint16_t follows)
6112
            {
6113
                uint16_t number;
6114
                return get_number(number) and sax->number_unsigned(number);
6115
            }
6116
6117
            case 0x1A: // Unsigned integer (four-byte uint32_t follows)
6118
            {
6119
                uint32_t number;
6120
                return get_number(number) and sax->number_unsigned(number);
6121
            }
6122
6123
            case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
6124
            {
6125
                uint64_t number;
6126
                return get_number(number) and sax->number_unsigned(number);
6127
            }
6128
6129
            // Negative integer -1-0x00..-1-0x17 (-1..-24)
6130
            case 0x20:
6131
            case 0x21:
6132
            case 0x22:
6133
            case 0x23:
6134
            case 0x24:
6135
            case 0x25:
6136
            case 0x26:
6137
            case 0x27:
6138
            case 0x28:
6139
            case 0x29:
6140
            case 0x2A:
6141
            case 0x2B:
6142
            case 0x2C:
6143
            case 0x2D:
6144
            case 0x2E:
6145
            case 0x2F:
6146
            case 0x30:
6147
            case 0x31:
6148
            case 0x32:
6149
            case 0x33:
6150
            case 0x34:
6151
            case 0x35:
6152
            case 0x36:
6153
            case 0x37:
6154
                return sax->number_integer(static_cast<int8_t>(0x20 - 1 - current));
6155
6156
            case 0x38: // Negative integer (one-byte uint8_t follows)
6157
            {
6158
                uint8_t number;
6159
                return get_number(number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
6160
            }
6161
6162
            case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
6163
            {
6164
                uint16_t number;
6165
                return get_number(number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
6166
            }
6167
6168
            case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
6169
            {
6170
                uint32_t number;
6171
                return get_number(number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
6172
            }
6173
6174
            case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
6175
            {
6176
                uint64_t number;
6177
                return get_number(number) and sax->number_integer(static_cast<number_integer_t>(-1)
6178
                        - static_cast<number_integer_t>(number));
6179
            }
6180
6181
            // UTF-8 string (0x00..0x17 bytes follow)
6182
            case 0x60:
6183
            case 0x61:
6184
            case 0x62:
6185
            case 0x63:
6186
            case 0x64:
6187
            case 0x65:
6188
            case 0x66:
6189
            case 0x67:
6190
            case 0x68:
6191
            case 0x69:
6192
            case 0x6A:
6193
            case 0x6B:
6194
            case 0x6C:
6195
            case 0x6D:
6196
            case 0x6E:
6197
            case 0x6F:
6198
            case 0x70:
6199
            case 0x71:
6200
            case 0x72:
6201
            case 0x73:
6202
            case 0x74:
6203
            case 0x75:
6204
            case 0x76:
6205
            case 0x77:
6206
            case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
6207
            case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
6208
            case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
6209
            case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
6210
            case 0x7F: // UTF-8 string (indefinite length)
6211
            {
6212
                string_t s;
6213
                return get_cbor_string(s) and sax->string(s);
6214
            }
6215
6216
            // array (0x00..0x17 data items follow)
6217
            case 0x80:
6218
            case 0x81:
6219
            case 0x82:
6220
            case 0x83:
6221
            case 0x84:
6222
            case 0x85:
6223
            case 0x86:
6224
            case 0x87:
6225
            case 0x88:
6226
            case 0x89:
6227
            case 0x8A:
6228
            case 0x8B:
6229
            case 0x8C:
6230
            case 0x8D:
6231
            case 0x8E:
6232
            case 0x8F:
6233
            case 0x90:
6234
            case 0x91:
6235
            case 0x92:
6236
            case 0x93:
6237
            case 0x94:
6238
            case 0x95:
6239
            case 0x96:
6240
            case 0x97:
6241
                return get_cbor_array(static_cast<std::size_t>(current & 0x1F));
6242
6243
            case 0x98: // array (one-byte uint8_t for n follows)
6244
            {
6245
                uint8_t len;
6246
                return get_number(len) and get_cbor_array(static_cast<std::size_t>(len));
6247
            }
6248
6249
            case 0x99: // array (two-byte uint16_t for n follow)
6250
            {
6251
                uint16_t len;
6252
                return get_number(len) and get_cbor_array(static_cast<std::size_t>(len));
6253
            }
6254
6255
            case 0x9A: // array (four-byte uint32_t for n follow)
6256
            {
6257
                uint32_t len;
6258
                return get_number(len) and get_cbor_array(static_cast<std::size_t>(len));
6259
            }
6260
6261
            case 0x9B: // array (eight-byte uint64_t for n follow)
6262
            {
6263
                uint64_t len;
6264
                return get_number(len) and get_cbor_array(static_cast<std::size_t>(len));
6265
            }
6266
6267
            case 0x9F: // array (indefinite length)
6268
                return get_cbor_array(std::size_t(-1));
6269
6270
            // map (0x00..0x17 pairs of data items follow)
6271
            case 0xA0:
6272
            case 0xA1:
6273
            case 0xA2:
6274
            case 0xA3:
6275
            case 0xA4:
6276
            case 0xA5:
6277
            case 0xA6:
6278
            case 0xA7:
6279
            case 0xA8:
6280
            case 0xA9:
6281
            case 0xAA:
6282
            case 0xAB:
6283
            case 0xAC:
6284
            case 0xAD:
6285
            case 0xAE:
6286
            case 0xAF:
6287
            case 0xB0:
6288
            case 0xB1:
6289
            case 0xB2:
6290
            case 0xB3:
6291
            case 0xB4:
6292
            case 0xB5:
6293
            case 0xB6:
6294
            case 0xB7:
6295
                return get_cbor_object(static_cast<std::size_t>(current & 0x1F));
6296
6297
            case 0xB8: // map (one-byte uint8_t for n follows)
6298
            {
6299
                uint8_t len;
6300
                return get_number(len) and get_cbor_object(static_cast<std::size_t>(len));
6301
            }
6302
6303
            case 0xB9: // map (two-byte uint16_t for n follow)
6304
            {
6305
                uint16_t len;
6306
                return get_number(len) and get_cbor_object(static_cast<std::size_t>(len));
6307
            }
6308
6309
            case 0xBA: // map (four-byte uint32_t for n follow)
6310
            {
6311
                uint32_t len;
6312
                return get_number(len) and get_cbor_object(static_cast<std::size_t>(len));
6313
            }
6314
6315
            case 0xBB: // map (eight-byte uint64_t for n follow)
6316
            {
6317
                uint64_t len;
6318
                return get_number(len) and get_cbor_object(static_cast<std::size_t>(len));
6319
            }
6320
6321
            case 0xBF: // map (indefinite length)
6322
                return get_cbor_object(std::size_t(-1));
6323
6324
            case 0xF4: // false
6325
                return sax->boolean(false);
6326
6327
            case 0xF5: // true
6328
                return sax->boolean(true);
6329
6330
            case 0xF6: // null
6331
                return sax->null();
6332
6333
            case 0xF9: // Half-Precision Float (two-byte IEEE 754)
6334
            {
6335
                const int byte1 = get();
6336
                if (JSON_UNLIKELY(not unexpect_eof()))
6337
                {
6338
                    return false;
6339
                }
6340
                const int byte2 = get();
6341
                if (JSON_UNLIKELY(not unexpect_eof()))
6342
                {
6343
                    return false;
6344
                }
6345
6346
                // code from RFC 7049, Appendix D, Figure 3:
6347
                // As half-precision floating-point numbers were only added
6348
                // to IEEE 754 in 2008, today's programming platforms often
6349
                // still only have limited support for them. It is very
6350
                // easy to include at least decoding support for them even
6351
                // without such support. An example of a small decoder for
6352
                // half-precision floating-point numbers in the C language
6353
                // is shown in Fig. 3.
6354
                const int half = (byte1 << 8) + byte2;
6355
                const double val = [&half]
6356
                {
6357
                    const int exp = (half >> 10) & 0x1F;
6358
                    const int mant = half & 0x3FF;
6359
                    assert(0 <= exp and exp <= 32);
6360
                    assert(0 <= mant and mant <= 1024);
6361
                    switch (exp)
6362
                    {
6363
                        case 0:
6364
                            return std::ldexp(mant, -24);
6365
                        case 31:
6366
                            return (mant == 0)
6367
                            ? std::numeric_limits<double>::infinity()
6368
                            : std::numeric_limits<double>::quiet_NaN();
6369
                        default:
6370
                            return std::ldexp(mant + 1024, exp - 25);
6371
                    }
6372
                }();
6373
                return sax->number_float((half & 0x8000) != 0
6374
                                         ? static_cast<number_float_t>(-val)
6375
                                         : static_cast<number_float_t>(val), "");
6376
            }
6377
6378
            case 0xFA: // Single-Precision Float (four-byte IEEE 754)
6379
            {
6380
                float number;
6381
                return get_number(number) and sax->number_float(static_cast<number_float_t>(number), "");
6382
            }
6383
6384
            case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
6385
            {
6386
                double number;
6387
                return get_number(number) and sax->number_float(static_cast<number_float_t>(number), "");
6388
            }
6389
6390
            default: // anything else (0xFF is handled inside the other types)
6391
            {
6392
                auto last_token = get_token_string();
6393
                return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, "error reading CBOR; last byte: 0x" + last_token));
6394
            }
6395
        }
6396
    }
6397
6398
    /*!
6399
    @return whether a valid MessagePack value was passed to the SAX parser
6400
    */
6401
    bool parse_msgpack_internal()
6402
    {
6403
        switch (get())
6404
        {
6405
            // EOF
6406
            case std::char_traits<char>::eof():
6407
                return unexpect_eof();
6408
6409
            // positive fixint
6410
            case 0x00:
6411
            case 0x01:
6412
            case 0x02:
6413
            case 0x03:
6414
            case 0x04:
6415
            case 0x05:
6416
            case 0x06:
6417
            case 0x07:
6418
            case 0x08:
6419
            case 0x09:
6420
            case 0x0A:
6421
            case 0x0B:
6422
            case 0x0C:
6423
            case 0x0D:
6424
            case 0x0E:
6425
            case 0x0F:
6426
            case 0x10:
6427
            case 0x11:
6428
            case 0x12:
6429
            case 0x13:
6430
            case 0x14:
6431
            case 0x15:
6432
            case 0x16:
6433
            case 0x17:
6434
            case 0x18:
6435
            case 0x19:
6436
            case 0x1A:
6437
            case 0x1B:
6438
            case 0x1C:
6439
            case 0x1D:
6440
            case 0x1E:
6441
            case 0x1F:
6442
            case 0x20:
6443
            case 0x21:
6444
            case 0x22:
6445
            case 0x23:
6446
            case 0x24:
6447
            case 0x25:
6448
            case 0x26:
6449
            case 0x27:
6450
            case 0x28:
6451
            case 0x29:
6452
            case 0x2A:
6453
            case 0x2B:
6454
            case 0x2C:
6455
            case 0x2D:
6456
            case 0x2E:
6457
            case 0x2F:
6458
            case 0x30:
6459
            case 0x31:
6460
            case 0x32:
6461
            case 0x33:
6462
            case 0x34:
6463
            case 0x35:
6464
            case 0x36:
6465
            case 0x37:
6466
            case 0x38:
6467
            case 0x39:
6468
            case 0x3A:
6469
            case 0x3B:
6470
            case 0x3C:
6471
            case 0x3D:
6472
            case 0x3E:
6473
            case 0x3F:
6474
            case 0x40:
6475
            case 0x41:
6476
            case 0x42:
6477
            case 0x43:
6478
            case 0x44:
6479
            case 0x45:
6480
            case 0x46:
6481
            case 0x47:
6482
            case 0x48:
6483
            case 0x49:
6484
            case 0x4A:
6485
            case 0x4B:
6486
            case 0x4C:
6487
            case 0x4D:
6488
            case 0x4E:
6489
            case 0x4F:
6490
            case 0x50:
6491
            case 0x51:
6492
            case 0x52:
6493
            case 0x53:
6494
            case 0x54:
6495
            case 0x55:
6496
            case 0x56:
6497
            case 0x57:
6498
            case 0x58:
6499
            case 0x59:
6500
            case 0x5A:
6501
            case 0x5B:
6502
            case 0x5C:
6503
            case 0x5D:
6504
            case 0x5E:
6505
            case 0x5F:
6506
            case 0x60:
6507
            case 0x61:
6508
            case 0x62:
6509
            case 0x63:
6510
            case 0x64:
6511
            case 0x65:
6512
            case 0x66:
6513
            case 0x67:
6514
            case 0x68:
6515
            case 0x69:
6516
            case 0x6A:
6517
            case 0x6B:
6518
            case 0x6C:
6519
            case 0x6D:
6520
            case 0x6E:
6521
            case 0x6F:
6522
            case 0x70:
6523
            case 0x71:
6524
            case 0x72:
6525
            case 0x73:
6526
            case 0x74:
6527
            case 0x75:
6528
            case 0x76:
6529
            case 0x77:
6530
            case 0x78:
6531
            case 0x79:
6532
            case 0x7A:
6533
            case 0x7B:
6534
            case 0x7C:
6535
            case 0x7D:
6536
            case 0x7E:
6537
            case 0x7F:
6538
                return sax->number_unsigned(static_cast<number_unsigned_t>(current));
6539
6540
            // fixmap
6541
            case 0x80:
6542
            case 0x81:
6543
            case 0x82:
6544
            case 0x83:
6545
            case 0x84:
6546
            case 0x85:
6547
            case 0x86:
6548
            case 0x87:
6549
            case 0x88:
6550
            case 0x89:
6551
            case 0x8A:
6552
            case 0x8B:
6553
            case 0x8C:
6554
            case 0x8D:
6555
            case 0x8E:
6556
            case 0x8F:
6557
                return get_msgpack_object(static_cast<std::size_t>(current & 0x0F));
6558
6559
            // fixarray
6560
            case 0x90:
6561
            case 0x91:
6562
            case 0x92:
6563
            case 0x93:
6564
            case 0x94:
6565
            case 0x95:
6566
            case 0x96:
6567
            case 0x97:
6568
            case 0x98:
6569
            case 0x99:
6570
            case 0x9A:
6571
            case 0x9B:
6572
            case 0x9C:
6573
            case 0x9D:
6574
            case 0x9E:
6575
            case 0x9F:
6576
                return get_msgpack_array(static_cast<std::size_t>(current & 0x0F));
6577
6578
            // fixstr
6579
            case 0xA0:
6580
            case 0xA1:
6581
            case 0xA2:
6582
            case 0xA3:
6583
            case 0xA4:
6584
            case 0xA5:
6585
            case 0xA6:
6586
            case 0xA7:
6587
            case 0xA8:
6588
            case 0xA9:
6589
            case 0xAA:
6590
            case 0xAB:
6591
            case 0xAC:
6592
            case 0xAD:
6593
            case 0xAE:
6594
            case 0xAF:
6595
            case 0xB0:
6596
            case 0xB1:
6597
            case 0xB2:
6598
            case 0xB3:
6599
            case 0xB4:
6600
            case 0xB5:
6601
            case 0xB6:
6602
            case 0xB7:
6603
            case 0xB8:
6604
            case 0xB9:
6605
            case 0xBA:
6606
            case 0xBB:
6607
            case 0xBC:
6608
            case 0xBD:
6609
            case 0xBE:
6610
            case 0xBF:
6611
            {
6612
                string_t s;
6613
                return get_msgpack_string(s) and sax->string(s);
6614
            }
6615
6616
            case 0xC0: // nil
6617
                return sax->null();
6618
6619
            case 0xC2: // false
6620
                return sax->boolean(false);
6621
6622
            case 0xC3: // true
6623
                return sax->boolean(true);
6624
6625
            case 0xCA: // float 32
6626
            {
6627
                float number;
6628
                return get_number(number) and sax->number_float(static_cast<number_float_t>(number), "");
6629
            }
6630
6631
            case 0xCB: // float 64
6632
            {
6633
                double number;
6634
                return get_number(number) and sax->number_float(static_cast<number_float_t>(number), "");
6635
            }
6636
6637
            case 0xCC: // uint 8
6638
            {
6639
                uint8_t number;
6640
                return get_number(number) and sax->number_unsigned(number);
6641
            }
6642
6643
            case 0xCD: // uint 16
6644
            {
6645
                uint16_t number;
6646
                return get_number(number) and sax->number_unsigned(number);
6647
            }
6648
6649
            case 0xCE: // uint 32
6650
            {
6651
                uint32_t number;
6652
                return get_number(number) and sax->number_unsigned(number);
6653
            }
6654
6655
            case 0xCF: // uint 64
6656
            {
6657
                uint64_t number;
6658
                return get_number(number) and sax->number_unsigned(number);
6659
            }
6660
6661
            case 0xD0: // int 8
6662
            {
6663
                int8_t number;
6664
                return get_number(number) and sax->number_integer(number);
6665
            }
6666
6667
            case 0xD1: // int 16
6668
            {
6669
                int16_t number;
6670
                return get_number(number) and sax->number_integer(number);
6671
            }
6672
6673
            case 0xD2: // int 32
6674
            {
6675
                int32_t number;
6676
                return get_number(number) and sax->number_integer(number);
6677
            }
6678
6679
            case 0xD3: // int 64
6680
            {
6681
                int64_t number;
6682
                return get_number(number) and sax->number_integer(number);
6683
            }
6684
6685
            case 0xD9: // str 8
6686
            case 0xDA: // str 16
6687
            case 0xDB: // str 32
6688
            {
6689
                string_t s;
6690
                return get_msgpack_string(s) and sax->string(s);
6691
            }
6692
6693
            case 0xDC: // array 16
6694
            {
6695
                uint16_t len;
6696
                return get_number(len) and get_msgpack_array(static_cast<std::size_t>(len));
6697
            }
6698
6699
            case 0xDD: // array 32
6700
            {
6701
                uint32_t len;
6702
                return get_number(len) and get_msgpack_array(static_cast<std::size_t>(len));
6703
            }
6704
6705
            case 0xDE: // map 16
6706
            {
6707
                uint16_t len;
6708
                return get_number(len) and get_msgpack_object(static_cast<std::size_t>(len));
6709
            }
6710
6711
            case 0xDF: // map 32
6712
            {
6713
                uint32_t len;
6714
                return get_number(len) and get_msgpack_object(static_cast<std::size_t>(len));
6715
            }
6716
6717
            // negative fixint
6718
            case 0xE0:
6719
            case 0xE1:
6720
            case 0xE2:
6721
            case 0xE3:
6722
            case 0xE4:
6723
            case 0xE5:
6724
            case 0xE6:
6725
            case 0xE7:
6726
            case 0xE8:
6727
            case 0xE9:
6728
            case 0xEA:
6729
            case 0xEB:
6730
            case 0xEC:
6731
            case 0xED:
6732
            case 0xEE:
6733
            case 0xEF:
6734
            case 0xF0:
6735
            case 0xF1:
6736
            case 0xF2:
6737
            case 0xF3:
6738
            case 0xF4:
6739
            case 0xF5:
6740
            case 0xF6:
6741
            case 0xF7:
6742
            case 0xF8:
6743
            case 0xF9:
6744
            case 0xFA:
6745
            case 0xFB:
6746
            case 0xFC:
6747
            case 0xFD:
6748
            case 0xFE:
6749
            case 0xFF:
6750
                return sax->number_integer(static_cast<int8_t>(current));
6751
6752
            default: // anything else
6753
            {
6754
                auto last_token = get_token_string();
6755
                return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, "error reading MessagePack; last byte: 0x" + last_token));
6756
            }
6757
        }
6758
    }
6759
6760
    /*!
6761
    @param[in] get_char  whether a new character should be retrieved from the
6762
                         input (true, default) or whether the last read
6763
                         character should be considered instead
6764
6765
    @return whether a valid UBJSON value was passed to the SAX parser
6766
    */
6767
    bool parse_ubjson_internal(const bool get_char = true)
6768
    {
6769
        return get_ubjson_value(get_char ? get_ignore_noop() : current);
6770
    }
6771
6772
    /*!
6773
    @brief get next character from the input
6774
6775
    This function provides the interface to the used input adapter. It does
6776
    not throw in case the input reached EOF, but returns a -'ve valued
6777
    `std::char_traits<char>::eof()` in that case.
6778
6779
    @return character read from the input
6780
    */
6781
    int get()
6782
    {
6783
        ++chars_read;
6784
        return (current = ia->get_character());
6785
    }
6786
6787
    /*!
6788
    @return character read from the input after ignoring all 'N' entries
6789
    */
6790
    int get_ignore_noop()
6791
    {
6792
        do
6793
        {
6794
            get();
6795
        }
6796
        while (current == 'N');
6797
6798
        return current;
6799
    }
6800
6801
    /*
6802
    @brief read a number from the input
6803
6804
    @tparam NumberType the type of the number
6805
    @param[out] result  number of type @a NumberType
6806
6807
    @return whether conversion completed
6808
6809
    @note This function needs to respect the system's endianess, because
6810
          bytes in CBOR, MessagePack, and UBJSON are stored in network order
6811
          (big endian) and therefore need reordering on little endian systems.
6812
    */
6813
    template<typename NumberType>
6814
    bool get_number(NumberType& result)
6815
    {
6816
        // step 1: read input into array with system's byte order
6817
        std::array<uint8_t, sizeof(NumberType)> vec;
6818
        for (std::size_t i = 0; i < sizeof(NumberType); ++i)
6819
        {
6820
            get();
6821
            if (JSON_UNLIKELY(not unexpect_eof()))
6822
            {
6823
                return false;
6824
            }
6825
6826
            // reverse byte order prior to conversion if necessary
6827
            if (is_little_endian)
6828
            {
6829
                vec[sizeof(NumberType) - i - 1] = static_cast<uint8_t>(current);
6830
            }
6831
            else
6832
            {
6833
                vec[i] = static_cast<uint8_t>(current); // LCOV_EXCL_LINE
6834
            }
6835
        }
6836
6837
        // step 2: convert array into number of type T and return
6838
        std::memcpy(&result, vec.data(), sizeof(NumberType));
6839
        return true;
6840
    }
6841
6842
    /*!
6843
    @brief create a string by reading characters from the input
6844
6845
    @tparam NumberType the type of the number
6846
    @param[in] len number of characters to read
6847
    @param[out] string created by reading @a len bytes
6848
6849
    @return whether string creation completed
6850
6851
    @note We can not reserve @a len bytes for the result, because @a len
6852
          may be too large. Usually, @ref unexpect_eof() detects the end of
6853
          the input before we run out of string memory.
6854
    */
6855
    template<typename NumberType>
6856
    bool get_string(const NumberType len, string_t& result)
6857
    {
6858
        bool success = true;
6859
        std::generate_n(std::back_inserter(result), len, [this, &success]()
6860
        {
6861
            get();
6862
            if (JSON_UNLIKELY(not unexpect_eof()))
6863
            {
6864
                success = false;
6865
            }
6866
            return static_cast<char>(current);
6867
        });
6868
        return success;
6869
    }
6870
6871
    /*!
6872
    @brief reads a CBOR string
6873
6874
    This function first reads starting bytes to determine the expected
6875
    string length and then copies this number of bytes into a string.
6876
    Additionally, CBOR's strings with indefinite lengths are supported.
6877
6878
    @param[out] result  created string
6879
6880
    @return whether string creation completed
6881
    */
6882
    bool get_cbor_string(string_t& result)
6883
    {
6884
        if (JSON_UNLIKELY(not unexpect_eof()))
6885
        {
6886
            return false;
6887
        }
6888
6889
        switch (current)
6890
        {
6891
            // UTF-8 string (0x00..0x17 bytes follow)
6892
            case 0x60:
6893
            case 0x61:
6894
            case 0x62:
6895
            case 0x63:
6896
            case 0x64:
6897
            case 0x65:
6898
            case 0x66:
6899
            case 0x67:
6900
            case 0x68:
6901
            case 0x69:
6902
            case 0x6A:
6903
            case 0x6B:
6904
            case 0x6C:
6905
            case 0x6D:
6906
            case 0x6E:
6907
            case 0x6F:
6908
            case 0x70:
6909
            case 0x71:
6910
            case 0x72:
6911
            case 0x73:
6912
            case 0x74:
6913
            case 0x75:
6914
            case 0x76:
6915
            case 0x77:
6916
            {
6917
                return get_string(current & 0x1F, result);
6918
            }
6919
6920
            case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
6921
            {
6922
                uint8_t len;
6923
                return get_number(len) and get_string(len, result);
6924
            }
6925
6926
            case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
6927
            {
6928
                uint16_t len;
6929
                return get_number(len) and get_string(len, result);
6930
            }
6931
6932
            case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
6933
            {
6934
                uint32_t len;
6935
                return get_number(len) and get_string(len, result);
6936
            }
6937
6938
            case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
6939
            {
6940
                uint64_t len;
6941
                return get_number(len) and get_string(len, result);
6942
            }
6943
6944
            case 0x7F: // UTF-8 string (indefinite length)
6945
            {
6946
                while (get() != 0xFF)
6947
                {
6948
                    string_t chunk;
6949
                    if (not get_cbor_string(chunk))
6950
                    {
6951
                        return false;
6952
                    }
6953
                    result.append(chunk);
6954
                }
6955
                return true;
6956
            }
6957
6958
            default:
6959
            {
6960
                auto last_token = get_token_string();
6961
                return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, "expected a CBOR string; last byte: 0x" + last_token));
6962
            }
6963
        }
6964
    }
6965
6966
    /*!
6967
    @param[in] len  the length of the array or std::size_t(-1) for an
6968
                    array of indefinite size
6969
    @return whether array creation completed
6970
    */
6971
    bool get_cbor_array(const std::size_t len)
6972
    {
6973
        if (JSON_UNLIKELY(not sax->start_array(len)))
6974
        {
6975
            return false;
6976
        }
6977
6978
        if (len != std::size_t(-1))
6979
            for (std::size_t i = 0; i < len; ++i)
6980
            {
6981
                if (JSON_UNLIKELY(not parse_cbor_internal()))
6982
                {
6983
                    return false;
6984
                }
6985
            }
6986
        else
6987
        {
6988
            while (get() != 0xFF)
6989
            {
6990
                if (JSON_UNLIKELY(not parse_cbor_internal(false)))
6991
                {
6992
                    return false;
6993
                }
6994
            }
6995
        }
6996
6997
        return sax->end_array();
6998
    }
6999
7000
    /*!
7001
    @param[in] len  the length of the object or std::size_t(-1) for an
7002
                    object of indefinite size
7003
    @return whether object creation completed
7004
    */
7005
    bool get_cbor_object(const std::size_t len)
7006
    {
7007
        if (not JSON_UNLIKELY(sax->start_object(len)))
7008
        {
7009
            return false;
7010
        }
7011
7012
        string_t key;
7013
        if (len != std::size_t(-1))
7014
        {
7015
            for (std::size_t i = 0; i < len; ++i)
7016
            {
7017
                get();
7018
                if (JSON_UNLIKELY(not get_cbor_string(key) or not sax->key(key)))
7019
                {
7020
                    return false;
7021
                }
7022
7023
                if (JSON_UNLIKELY(not parse_cbor_internal()))
7024
                {
7025
                    return false;
7026
                }
7027
                key.clear();
7028
            }
7029
        }
7030
        else
7031
        {
7032
            while (get() != 0xFF)
7033
            {
7034
                if (JSON_UNLIKELY(not get_cbor_string(key) or not sax->key(key)))
7035
                {
7036
                    return false;
7037
                }
7038
7039
                if (JSON_UNLIKELY(not parse_cbor_internal()))
7040
                {
7041
                    return false;
7042
                }
7043
                key.clear();
7044
            }
7045
        }
7046
7047
        return sax->end_object();
7048
    }
7049
7050
    /*!
7051
    @brief reads a MessagePack string
7052
7053
    This function first reads starting bytes to determine the expected
7054
    string length and then copies this number of bytes into a string.
7055
7056
    @param[out] result  created string
7057
7058
    @return whether string creation completed
7059
    */
7060
    bool get_msgpack_string(string_t& result)
7061
    {
7062
        if (JSON_UNLIKELY(not unexpect_eof()))
7063
        {
7064
            return false;
7065
        }
7066
7067
        switch (current)
7068
        {
7069
            // fixstr
7070
            case 0xA0:
7071
            case 0xA1:
7072
            case 0xA2:
7073
            case 0xA3:
7074
            case 0xA4:
7075
            case 0xA5:
7076
            case 0xA6:
7077
            case 0xA7:
7078
            case 0xA8:
7079
            case 0xA9:
7080
            case 0xAA:
7081
            case 0xAB:
7082
            case 0xAC:
7083
            case 0xAD:
7084
            case 0xAE:
7085
            case 0xAF:
7086
            case 0xB0:
7087
            case 0xB1:
7088
            case 0xB2:
7089
            case 0xB3:
7090
            case 0xB4:
7091
            case 0xB5:
7092
            case 0xB6:
7093
            case 0xB7:
7094
            case 0xB8:
7095
            case 0xB9:
7096
            case 0xBA:
7097
            case 0xBB:
7098
            case 0xBC:
7099
            case 0xBD:
7100
            case 0xBE:
7101
            case 0xBF:
7102
            {
7103
                return get_string(current & 0x1F, result);
7104
            }
7105
7106
            case 0xD9: // str 8
7107
            {
7108
                uint8_t len;
7109
                return get_number(len) and get_string(len, result);
7110
            }
7111
7112
            case 0xDA: // str 16
7113
            {
7114
                uint16_t len;
7115
                return get_number(len) and get_string(len, result);
7116
            }
7117
7118
            case 0xDB: // str 32
7119
            {
7120
                uint32_t len;
7121
                return get_number(len) and get_string(len, result);
7122
            }
7123
7124
            default:
7125
            {
7126
                auto last_token = get_token_string();
7127
                return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, "expected a MessagePack string; last byte: 0x" + last_token));
7128
            }
7129
        }
7130
    }
7131
7132
    /*!
7133
    @param[in] len  the length of the array
7134
    @return whether array creation completed
7135
    */
7136
    bool get_msgpack_array(const std::size_t len)
7137
    {
7138
        if (JSON_UNLIKELY(not sax->start_array(len)))
7139
        {
7140
            return false;
7141
        }
7142
7143
        for (std::size_t i = 0; i < len; ++i)
7144
        {
7145
            if (JSON_UNLIKELY(not parse_msgpack_internal()))
7146
            {
7147
                return false;
7148
            }
7149
        }
7150
7151
        return sax->end_array();
7152
    }
7153
7154
    /*!
7155
    @param[in] len  the length of the object
7156
    @return whether object creation completed
7157
    */
7158
    bool get_msgpack_object(const std::size_t len)
7159
    {
7160
        if (JSON_UNLIKELY(not sax->start_object(len)))
7161
        {
7162
            return false;
7163
        }
7164
7165
        string_t key;
7166
        for (std::size_t i = 0; i < len; ++i)
7167
        {
7168
            get();
7169
            if (JSON_UNLIKELY(not get_msgpack_string(key) or not sax->key(key)))
7170
            {
7171
                return false;
7172
            }
7173
7174
            if (JSON_UNLIKELY(not parse_msgpack_internal()))
7175
            {
7176
                return false;
7177
            }
7178
            key.clear();
7179
        }
7180
7181
        return sax->end_object();
7182
    }
7183
7184
    /*!
7185
    @brief reads a UBJSON string
7186
7187
    This function is either called after reading the 'S' byte explicitly
7188
    indicating a string, or in case of an object key where the 'S' byte can be
7189
    left out.
7190
7191
    @param[out] result   created string
7192
    @param[in] get_char  whether a new character should be retrieved from the
7193
                         input (true, default) or whether the last read
7194
                         character should be considered instead
7195
7196
    @return whether string creation completed
7197
    */
7198
    bool get_ubjson_string(string_t& result, const bool get_char = true)
7199
    {
7200
        if (get_char)
7201
        {
7202
            get();  // TODO: may we ignore N here?
7203
        }
7204
7205
        if (JSON_UNLIKELY(not unexpect_eof()))
7206
        {
7207
            return false;
7208
        }
7209
7210
        switch (current)
7211
        {
7212
            case 'U':
7213
            {
7214
                uint8_t len;
7215
                return get_number(len) and get_string(len, result);
7216
            }
7217
7218
            case 'i':
7219
            {
7220
                int8_t len;
7221
                return get_number(len) and get_string(len, result);
7222
            }
7223
7224
            case 'I':
7225
            {
7226
                int16_t len;
7227
                return get_number(len) and get_string(len, result);
7228
            }
7229
7230
            case 'l':
7231
            {
7232
                int32_t len;
7233
                return get_number(len) and get_string(len, result);
7234
            }
7235
7236
            case 'L':
7237
            {
7238
                int64_t len;
7239
                return get_number(len) and get_string(len, result);
7240
            }
7241
7242
            default:
7243
                auto last_token = get_token_string();
7244
                return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, "expected a UBJSON string; last byte: 0x" + last_token));
7245
        }
7246
    }
7247
7248
    /*!
7249
    @param[out] result  determined size
7250
    @return whether size determination completed
7251
    */
7252
    bool get_ubjson_size_value(std::size_t& result)
7253
    {
7254
        switch (get_ignore_noop())
7255
        {
7256
            case 'U':
7257
            {
7258
                uint8_t number;
7259
                if (JSON_UNLIKELY(not get_number(number)))
7260
                {
7261
                    return false;
7262
                }
7263
                result = static_cast<std::size_t>(number);
7264
                return true;
7265
            }
7266
7267
            case 'i':
7268
            {
7269
                int8_t number;
7270
                if (JSON_UNLIKELY(not get_number(number)))
7271
                {
7272
                    return false;
7273
                }
7274
                result = static_cast<std::size_t>(number);
7275
                return true;
7276
            }
7277
7278
            case 'I':
7279
            {
7280
                int16_t number;
7281
                if (JSON_UNLIKELY(not get_number(number)))
7282
                {
7283
                    return false;
7284
                }
7285
                result = static_cast<std::size_t>(number);
7286
                return true;
7287
            }
7288
7289
            case 'l':
7290
            {
7291
                int32_t number;
7292
                if (JSON_UNLIKELY(not get_number(number)))
7293
                {
7294
                    return false;
7295
                }
7296
                result = static_cast<std::size_t>(number);
7297
                return true;
7298
            }
7299
7300
            case 'L':
7301
            {
7302
                int64_t number;
7303
                if (JSON_UNLIKELY(not get_number(number)))
7304
                {
7305
                    return false;
7306
                }
7307
                result = static_cast<std::size_t>(number);
7308
                return true;
7309
            }
7310
7311
            default:
7312
            {
7313
                auto last_token = get_token_string();
7314
                return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, "byte after '#' must denote a number type; last byte: 0x" + last_token));
7315
            }
7316
        }
7317
    }
7318
7319
    /*!
7320
    @brief determine the type and size for a container
7321
7322
    In the optimized UBJSON format, a type and a size can be provided to allow
7323
    for a more compact representation.
7324
7325
    @param[out] result  pair of the size and the type
7326
7327
    @return whether pair creation completed
7328
    */
7329
    bool get_ubjson_size_type(std::pair<std::size_t, int>& result)
7330
    {
7331
        result.first = string_t::npos; // size
7332
        result.second = 0; // type
7333
7334
        get_ignore_noop();
7335
7336
        if (current == '$')
7337
        {
7338
            result.second = get();  // must not ignore 'N', because 'N' maybe the type
7339
            if (JSON_UNLIKELY(not unexpect_eof()))
7340
            {
7341
                return false;
7342
            }
7343
7344
            get_ignore_noop();
7345
            if (JSON_UNLIKELY(current != '#'))
7346
            {
7347
                if (JSON_UNLIKELY(not unexpect_eof()))
7348
                {
7349
                    return false;
7350
                }
7351
                auto last_token = get_token_string();
7352
                return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, "expected '#' after UBJSON type information; last byte: 0x" + last_token));
7353
            }
7354
7355
            return get_ubjson_size_value(result.first);
7356
        }
7357
        else if (current == '#')
7358
        {
7359
            return get_ubjson_size_value(result.first);
7360
        }
7361
        return true;
7362
    }
7363
7364
    /*!
7365
    @param prefix  the previously read or set type prefix
7366
    @return whether value creation completed
7367
    */
7368
    bool get_ubjson_value(const int prefix)
7369
    {
7370
        switch (prefix)
7371
        {
7372
            case std::char_traits<char>::eof():  // EOF
7373
                return unexpect_eof();
7374
7375
            case 'T':  // true
7376
                return sax->boolean(true);
7377
            case 'F':  // false
7378
                return sax->boolean(false);
7379
7380
            case 'Z':  // null
7381
                return sax->null();
7382
7383
            case 'U':
7384
            {
7385
                uint8_t number;
7386
                return get_number(number) and sax->number_unsigned(number);
7387
            }
7388
7389
            case 'i':
7390
            {
7391
                int8_t number;
7392
                return get_number(number) and sax->number_integer(number);
7393
            }
7394
7395
            case 'I':
7396
            {
7397
                int16_t number;
7398
                return get_number(number) and sax->number_integer(number);
7399
            }
7400
7401
            case 'l':
7402
            {
7403
                int32_t number;
7404
                return get_number(number) and sax->number_integer(number);
7405
            }
7406
7407
            case 'L':
7408
            {
7409
                int64_t number;
7410
                return get_number(number) and sax->number_integer(number);
7411
            }
7412
7413
            case 'd':
7414
            {
7415
                float number;
7416
                return get_number(number) and sax->number_float(static_cast<number_float_t>(number), "");
7417
            }
7418
7419
            case 'D':
7420
            {
7421
                double number;
7422
                return get_number(number) and sax->number_float(static_cast<number_float_t>(number), "");
7423
            }
7424
7425
            case 'C':  // char
7426
            {
7427
                get();
7428
                if (JSON_UNLIKELY(not unexpect_eof()))
7429
                {
7430
                    return false;
7431
                }
7432
                if (JSON_UNLIKELY(current > 127))
7433
                {
7434
                    auto last_token = get_token_string();
7435
                    return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + last_token));
7436
                }
7437
                string_t s(1, static_cast<char>(current));
7438
                return sax->string(s);
7439
            }
7440
7441
            case 'S':  // string
7442
            {
7443
                string_t s;
7444
                return get_ubjson_string(s) and sax->string(s);
7445
            }
7446
7447
            case '[':  // array
7448
                return get_ubjson_array();
7449
7450
            case '{':  // object
7451
                return get_ubjson_object();
7452
7453
            default: // anything else
7454
            {
7455
                auto last_token = get_token_string();
7456
                return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, "error reading UBJSON; last byte: 0x" + last_token));
7457
            }
7458
        }
7459
    }
7460
7461
    /*!
7462
    @return whether array creation completed
7463
    */
7464
    bool get_ubjson_array()
7465
    {
7466
        std::pair<std::size_t, int> size_and_type;
7467
        if (JSON_UNLIKELY(not get_ubjson_size_type(size_and_type)))
7468
        {
7469
            return false;
7470
        }
7471
7472
        if (size_and_type.first != string_t::npos)
7473
        {
7474
            if (JSON_UNLIKELY(not sax->start_array(size_and_type.first)))
7475
            {
7476
                return false;
7477
            }
7478
7479
            if (size_and_type.second != 0)
7480
            {
7481
                if (size_and_type.second != 'N')
7482
                {
7483
                    for (std::size_t i = 0; i < size_and_type.first; ++i)
7484
                    {
7485
                        if (JSON_UNLIKELY(not get_ubjson_value(size_and_type.second)))
7486
                        {
7487
                            return false;
7488
                        }
7489
                    }
7490
                }
7491
            }
7492
            else
7493
            {
7494
                for (std::size_t i = 0; i < size_and_type.first; ++i)
7495
                {
7496
                    if (JSON_UNLIKELY(not parse_ubjson_internal()))
7497
                    {
7498
                        return false;
7499
                    }
7500
                }
7501
            }
7502
        }
7503
        else
7504
        {
7505
            if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1))))
7506
            {
7507
                return false;
7508
            }
7509
7510
            while (current != ']')
7511
            {
7512
                if (JSON_UNLIKELY(not parse_ubjson_internal(false)))
7513
                {
7514
                    return false;
7515
                }
7516
                get_ignore_noop();
7517
            }
7518
        }
7519
7520
        return sax->end_array();
7521
    }
7522
7523
    /*!
7524
    @return whether object creation completed
7525
    */
7526
    bool get_ubjson_object()
7527
    {
7528
        std::pair<std::size_t, int> size_and_type;
7529
        if (JSON_UNLIKELY(not get_ubjson_size_type(size_and_type)))
7530
        {
7531
            return false;
7532
        }
7533
7534
        string_t key;
7535
        if (size_and_type.first != string_t::npos)
7536
        {
7537
            if (JSON_UNLIKELY(not sax->start_object(size_and_type.first)))
7538
            {
7539
                return false;
7540
            }
7541
7542
            if (size_and_type.second != 0)
7543
            {
7544
                for (std::size_t i = 0; i < size_and_type.first; ++i)
7545
                {
7546
                    if (JSON_UNLIKELY(not get_ubjson_string(key) or not sax->key(key)))
7547
                    {
7548
                        return false;
7549
                    }
7550
                    if (JSON_UNLIKELY(not get_ubjson_value(size_and_type.second)))
7551
                    {
7552
                        return false;
7553
                    }
7554
                    key.clear();
7555
                }
7556
            }
7557
            else
7558
            {
7559
                for (std::size_t i = 0; i < size_and_type.first; ++i)
7560
                {
7561
                    if (JSON_UNLIKELY(not get_ubjson_string(key) or not sax->key(key)))
7562
                    {
7563
                        return false;
7564
                    }
7565
                    if (JSON_UNLIKELY(not parse_ubjson_internal()))
7566
                    {
7567
                        return false;
7568
                    }
7569
                    key.clear();
7570
                }
7571
            }
7572
        }
7573
        else
7574
        {
7575
            if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1))))
7576
            {
7577
                return false;
7578
            }
7579
7580
            while (current != '}')
7581
            {
7582
                if (JSON_UNLIKELY(not get_ubjson_string(key, false) or not sax->key(key)))
7583
                {
7584
                    return false;
7585
                }
7586
                if (JSON_UNLIKELY(not parse_ubjson_internal()))
7587
                {
7588
                    return false;
7589
                }
7590
                get_ignore_noop();
7591
                key.clear();
7592
            }
7593
        }
7594
7595
        return sax->end_object();
7596
    }
7597
7598
    /*!
7599
    @return whether the last read character is not EOF
7600
    */
7601
    bool unexpect_eof() const
7602
    {
7603
        if (JSON_UNLIKELY(current == std::char_traits<char>::eof()))
7604
        {
7605
            return sax->parse_error(chars_read, "<end of file>", parse_error::create(110, chars_read, "unexpected end of input"));
7606
        }
7607
        return true;
7608
    }
7609
7610
    /*!
7611
    @return a string representation of the last read byte
7612
    */
7613
    std::string get_token_string() const
7614
    {
7615
        char cr[3];
7616
        snprintf(cr, 3, "%.2hhX", static_cast<unsigned char>(current));
7617
        return std::string{cr};
7618
    }
7619
7620
  private:
7621
    /// input adapter
7622
    input_adapter_t ia = nullptr;
7623
7624
    /// the current character
7625
    int current = std::char_traits<char>::eof();
7626
7627
    /// the number of characters read
7628
    std::size_t chars_read = 0;
7629
7630
    /// whether we can assume little endianess
7631
    const bool is_little_endian = little_endianess();
7632
7633
    /// the SAX parser
7634
    json_sax_t* sax = nullptr;
7635
};
7636
}
7637
}
7638
7639
// #include <nlohmann/detail/output/binary_writer.hpp>
7640
7641
7642
#include <algorithm> // reverse
7643
#include <array> // array
7644
#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
7645
#include <cstring> // memcpy
7646
#include <limits> // numeric_limits
7647
7648
// #include <nlohmann/detail/input/binary_reader.hpp>
7649
7650
// #include <nlohmann/detail/output/output_adapters.hpp>
7651
7652
7653
namespace nlohmann
7654
{
7655
namespace detail
7656
{
7657
///////////////////
7658
// binary writer //
7659
///////////////////
7660
7661
/*!
7662
@brief serialization to CBOR and MessagePack values
7663
*/
7664
template<typename BasicJsonType, typename CharType>
7665
class binary_writer
7666
{
7667
  public:
7668
    /*!
7669
    @brief create a binary writer
7670
7671
    @param[in] adapter  output adapter to write to
7672
    */
7673
    explicit binary_writer(output_adapter_t<CharType> adapter) : oa(adapter)
7674
    {
7675
        assert(oa);
7676
    }
7677
7678
    /*!
7679
    @brief[in] j  JSON value to serialize
7680
    */
7681
    void write_cbor(const BasicJsonType& j)
7682
    {
7683
        switch (j.type())
7684
        {
7685
            case value_t::null:
7686
            {
7687
                oa->write_character(static_cast<CharType>(0xF6));
7688
                break;
7689
            }
7690
7691
            case value_t::boolean:
7692
            {
7693
                oa->write_character(j.m_value.boolean
7694
                                    ? static_cast<CharType>(0xF5)
7695
                                    : static_cast<CharType>(0xF4));
7696
                break;
7697
            }
7698
7699
            case value_t::number_integer:
7700
            {
7701
                if (j.m_value.number_integer >= 0)
7702
                {
7703
                    // CBOR does not differentiate between positive signed
7704
                    // integers and unsigned integers. Therefore, we used the
7705
                    // code from the value_t::number_unsigned case here.
7706
                    if (j.m_value.number_integer <= 0x17)
7707
                    {
7708
                        write_number(static_cast<uint8_t>(j.m_value.number_integer));
7709
                    }
7710
                    else if (j.m_value.number_integer <= (std::numeric_limits<uint8_t>::max)())
7711
                    {
7712
                        oa->write_character(static_cast<CharType>(0x18));
7713
                        write_number(static_cast<uint8_t>(j.m_value.number_integer));
7714
                    }
7715
                    else if (j.m_value.number_integer <= (std::numeric_limits<uint16_t>::max)())
7716
                    {
7717
                        oa->write_character(static_cast<CharType>(0x19));
7718
                        write_number(static_cast<uint16_t>(j.m_value.number_integer));
7719
                    }
7720
                    else if (j.m_value.number_integer <= (std::numeric_limits<uint32_t>::max)())
7721
                    {
7722
                        oa->write_character(static_cast<CharType>(0x1A));
7723
                        write_number(static_cast<uint32_t>(j.m_value.number_integer));
7724
                    }
7725
                    else
7726
                    {
7727
                        oa->write_character(static_cast<CharType>(0x1B));
7728
                        write_number(static_cast<uint64_t>(j.m_value.number_integer));
7729
                    }
7730
                }
7731
                else
7732
                {
7733
                    // The conversions below encode the sign in the first
7734
                    // byte, and the value is converted to a positive number.
7735
                    const auto positive_number = -1 - j.m_value.number_integer;
7736
                    if (j.m_value.number_integer >= -24)
7737
                    {
7738
                        write_number(static_cast<uint8_t>(0x20 + positive_number));
7739
                    }
7740
                    else if (positive_number <= (std::numeric_limits<uint8_t>::max)())
7741
                    {
7742
                        oa->write_character(static_cast<CharType>(0x38));
7743
                        write_number(static_cast<uint8_t>(positive_number));
7744
                    }
7745
                    else if (positive_number <= (std::numeric_limits<uint16_t>::max)())
7746
                    {
7747
                        oa->write_character(static_cast<CharType>(0x39));
7748
                        write_number(static_cast<uint16_t>(positive_number));
7749
                    }
7750
                    else if (positive_number <= (std::numeric_limits<uint32_t>::max)())
7751
                    {
7752
                        oa->write_character(static_cast<CharType>(0x3A));
7753
                        write_number(static_cast<uint32_t>(positive_number));
7754
                    }
7755
                    else
7756
                    {
7757
                        oa->write_character(static_cast<CharType>(0x3B));
7758
                        write_number(static_cast<uint64_t>(positive_number));
7759
                    }
7760
                }
7761
                break;
7762
            }
7763
7764
            case value_t::number_unsigned:
7765
            {
7766
                if (j.m_value.number_unsigned <= 0x17)
7767
                {
7768
                    write_number(static_cast<uint8_t>(j.m_value.number_unsigned));
7769
                }
7770
                else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
7771
                {
7772
                    oa->write_character(static_cast<CharType>(0x18));
7773
                    write_number(static_cast<uint8_t>(j.m_value.number_unsigned));
7774
                }
7775
                else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
7776
                {
7777
                    oa->write_character(static_cast<CharType>(0x19));
7778
                    write_number(static_cast<uint16_t>(j.m_value.number_unsigned));
7779
                }
7780
                else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
7781
                {
7782
                    oa->write_character(static_cast<CharType>(0x1A));
7783
                    write_number(static_cast<uint32_t>(j.m_value.number_unsigned));
7784
                }
7785
                else
7786
                {
7787
                    oa->write_character(static_cast<CharType>(0x1B));
7788
                    write_number(static_cast<uint64_t>(j.m_value.number_unsigned));
7789
                }
7790
                break;
7791
            }
7792
7793
            case value_t::number_float:
7794
            {
7795
                oa->write_character(get_cbor_float_prefix(j.m_value.number_float));
7796
                write_number(j.m_value.number_float);
7797
                break;
7798
            }
7799
7800
            case value_t::string:
7801
            {
7802
                // step 1: write control byte and the string length
7803
                const auto N = j.m_value.string->size();
7804
                if (N <= 0x17)
7805
                {
7806
                    write_number(static_cast<uint8_t>(0x60 + N));
7807
                }
7808
                else if (N <= (std::numeric_limits<uint8_t>::max)())
7809
                {
7810
                    oa->write_character(static_cast<CharType>(0x78));
7811
                    write_number(static_cast<uint8_t>(N));
7812
                }
7813
                else if (N <= (std::numeric_limits<uint16_t>::max)())
7814
                {
7815
                    oa->write_character(static_cast<CharType>(0x79));
7816
                    write_number(static_cast<uint16_t>(N));
7817
                }
7818
                else if (N <= (std::numeric_limits<uint32_t>::max)())
7819
                {
7820
                    oa->write_character(static_cast<CharType>(0x7A));
7821
                    write_number(static_cast<uint32_t>(N));
7822
                }
7823
                // LCOV_EXCL_START
7824
                else if (N <= (std::numeric_limits<uint64_t>::max)())
7825
                {
7826
                    oa->write_character(static_cast<CharType>(0x7B));
7827
                    write_number(static_cast<uint64_t>(N));
7828
                }
7829
                // LCOV_EXCL_STOP
7830
7831
                // step 2: write the string
7832
                oa->write_characters(
7833
                    reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
7834
                    j.m_value.string->size());
7835
                break;
7836
            }
7837
7838
            case value_t::array:
7839
            {
7840
                // step 1: write control byte and the array size
7841
                const auto N = j.m_value.array->size();
7842
                if (N <= 0x17)
7843
                {
7844
                    write_number(static_cast<uint8_t>(0x80 + N));
7845
                }
7846
                else if (N <= (std::numeric_limits<uint8_t>::max)())
7847
                {
7848
                    oa->write_character(static_cast<CharType>(0x98));
7849
                    write_number(static_cast<uint8_t>(N));
7850
                }
7851
                else if (N <= (std::numeric_limits<uint16_t>::max)())
7852
                {
7853
                    oa->write_character(static_cast<CharType>(0x99));
7854
                    write_number(static_cast<uint16_t>(N));
7855
                }
7856
                else if (N <= (std::numeric_limits<uint32_t>::max)())
7857
                {
7858
                    oa->write_character(static_cast<CharType>(0x9A));
7859
                    write_number(static_cast<uint32_t>(N));
7860
                }
7861
                // LCOV_EXCL_START
7862
                else if (N <= (std::numeric_limits<uint64_t>::max)())
7863
                {
7864
                    oa->write_character(static_cast<CharType>(0x9B));
7865
                    write_number(static_cast<uint64_t>(N));
7866
                }
7867
                // LCOV_EXCL_STOP
7868
7869
                // step 2: write each element
7870
                for (const auto& el : *j.m_value.array)
7871
                {
7872
                    write_cbor(el);
7873
                }
7874
                break;
7875
            }
7876
7877
            case value_t::object:
7878
            {
7879
                // step 1: write control byte and the object size
7880
                const auto N = j.m_value.object->size();
7881
                if (N <= 0x17)
7882
                {
7883
                    write_number(static_cast<uint8_t>(0xA0 + N));
7884
                }
7885
                else if (N <= (std::numeric_limits<uint8_t>::max)())
7886
                {
7887
                    oa->write_character(static_cast<CharType>(0xB8));
7888
                    write_number(static_cast<uint8_t>(N));
7889
                }
7890
                else if (N <= (std::numeric_limits<uint16_t>::max)())
7891
                {
7892
                    oa->write_character(static_cast<CharType>(0xB9));
7893
                    write_number(static_cast<uint16_t>(N));
7894
                }
7895
                else if (N <= (std::numeric_limits<uint32_t>::max)())
7896
                {
7897
                    oa->write_character(static_cast<CharType>(0xBA));
7898
                    write_number(static_cast<uint32_t>(N));
7899
                }
7900
                // LCOV_EXCL_START
7901
                else if (N <= (std::numeric_limits<uint64_t>::max)())
7902
                {
7903
                    oa->write_character(static_cast<CharType>(0xBB));
7904
                    write_number(static_cast<uint64_t>(N));
7905
                }
7906
                // LCOV_EXCL_STOP
7907
7908
                // step 2: write each element
7909
                for (const auto& el : *j.m_value.object)
7910
                {
7911
                    write_cbor(el.first);
7912
                    write_cbor(el.second);
7913
                }
7914
                break;
7915
            }
7916
7917
            default:
7918
                break;
7919
        }
7920
    }
7921
7922
    /*!
7923
    @brief[in] j  JSON value to serialize
7924
    */
7925
    void write_msgpack(const BasicJsonType& j)
7926
    {
7927
        switch (j.type())
7928
        {
7929
            case value_t::null: // nil
7930
            {
7931
                oa->write_character(static_cast<CharType>(0xC0));
7932
                break;
7933
            }
7934
7935
            case value_t::boolean: // true and false
7936
            {
7937
                oa->write_character(j.m_value.boolean
7938
                                    ? static_cast<CharType>(0xC3)
7939
                                    : static_cast<CharType>(0xC2));
7940
                break;
7941
            }
7942
7943
            case value_t::number_integer:
7944
            {
7945
                if (j.m_value.number_integer >= 0)
7946
                {
7947
                    // MessagePack does not differentiate between positive
7948
                    // signed integers and unsigned integers. Therefore, we used
7949
                    // the code from the value_t::number_unsigned case here.
7950
                    if (j.m_value.number_unsigned < 128)
7951
                    {
7952
                        // positive fixnum
7953
                        write_number(static_cast<uint8_t>(j.m_value.number_integer));
7954
                    }
7955
                    else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
7956
                    {
7957
                        // uint 8
7958
                        oa->write_character(static_cast<CharType>(0xCC));
7959
                        write_number(static_cast<uint8_t>(j.m_value.number_integer));
7960
                    }
7961
                    else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
7962
                    {
7963
                        // uint 16
7964
                        oa->write_character(static_cast<CharType>(0xCD));
7965
                        write_number(static_cast<uint16_t>(j.m_value.number_integer));
7966
                    }
7967
                    else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
7968
                    {
7969
                        // uint 32
7970
                        oa->write_character(static_cast<CharType>(0xCE));
7971
                        write_number(static_cast<uint32_t>(j.m_value.number_integer));
7972
                    }
7973
                    else if (j.m_value.number_unsigned <= (std::numeric_limits<uint64_t>::max)())
7974
                    {
7975
                        // uint 64
7976
                        oa->write_character(static_cast<CharType>(0xCF));
7977
                        write_number(static_cast<uint64_t>(j.m_value.number_integer));
7978
                    }
7979
                }
7980
                else
7981
                {
7982
                    if (j.m_value.number_integer >= -32)
7983
                    {
7984
                        // negative fixnum
7985
                        write_number(static_cast<int8_t>(j.m_value.number_integer));
7986
                    }
7987
                    else if (j.m_value.number_integer >= (std::numeric_limits<int8_t>::min)() and
7988
                             j.m_value.number_integer <= (std::numeric_limits<int8_t>::max)())
7989
                    {
7990
                        // int 8
7991
                        oa->write_character(static_cast<CharType>(0xD0));
7992
                        write_number(static_cast<int8_t>(j.m_value.number_integer));
7993
                    }
7994
                    else if (j.m_value.number_integer >= (std::numeric_limits<int16_t>::min)() and
7995
                             j.m_value.number_integer <= (std::numeric_limits<int16_t>::max)())
7996
                    {
7997
                        // int 16
7998
                        oa->write_character(static_cast<CharType>(0xD1));
7999
                        write_number(static_cast<int16_t>(j.m_value.number_integer));
8000
                    }
8001
                    else if (j.m_value.number_integer >= (std::numeric_limits<int32_t>::min)() and
8002
                             j.m_value.number_integer <= (std::numeric_limits<int32_t>::max)())
8003
                    {
8004
                        // int 32
8005
                        oa->write_character(static_cast<CharType>(0xD2));
8006
                        write_number(static_cast<int32_t>(j.m_value.number_integer));
8007
                    }
8008
                    else if (j.m_value.number_integer >= (std::numeric_limits<int64_t>::min)() and
8009
                             j.m_value.number_integer <= (std::numeric_limits<int64_t>::max)())
8010
                    {
8011
                        // int 64
8012
                        oa->write_character(static_cast<CharType>(0xD3));
8013
                        write_number(static_cast<int64_t>(j.m_value.number_integer));
8014
                    }
8015
                }
8016
                break;
8017
            }
8018
8019
            case value_t::number_unsigned:
8020
            {
8021
                if (j.m_value.number_unsigned < 128)
8022
                {
8023
                    // positive fixnum
8024
                    write_number(static_cast<uint8_t>(j.m_value.number_integer));
8025
                }
8026
                else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
8027
                {
8028
                    // uint 8
8029
                    oa->write_character(static_cast<CharType>(0xCC));
8030
                    write_number(static_cast<uint8_t>(j.m_value.number_integer));
8031
                }
8032
                else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
8033
                {
8034
                    // uint 16
8035
                    oa->write_character(static_cast<CharType>(0xCD));
8036
                    write_number(static_cast<uint16_t>(j.m_value.number_integer));
8037
                }
8038
                else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
8039
                {
8040
                    // uint 32
8041
                    oa->write_character(static_cast<CharType>(0xCE));
8042
                    write_number(static_cast<uint32_t>(j.m_value.number_integer));
8043
                }
8044
                else if (j.m_value.number_unsigned <= (std::numeric_limits<uint64_t>::max)())
8045
                {
8046
                    // uint 64
8047
                    oa->write_character(static_cast<CharType>(0xCF));
8048
                    write_number(static_cast<uint64_t>(j.m_value.number_integer));
8049
                }
8050
                break;
8051
            }
8052
8053
            case value_t::number_float:
8054
            {
8055
                oa->write_character(get_msgpack_float_prefix(j.m_value.number_float));
8056
                write_number(j.m_value.number_float);
8057
                break;
8058
            }
8059
8060
            case value_t::string:
8061
            {
8062
                // step 1: write control byte and the string length
8063
                const auto N = j.m_value.string->size();
8064
                if (N <= 31)
8065
                {
8066
                    // fixstr
8067
                    write_number(static_cast<uint8_t>(0xA0 | N));
8068
                }
8069
                else if (N <= (std::numeric_limits<uint8_t>::max)())
8070
                {
8071
                    // str 8
8072
                    oa->write_character(static_cast<CharType>(0xD9));
8073
                    write_number(static_cast<uint8_t>(N));
8074
                }
8075
                else if (N <= (std::numeric_limits<uint16_t>::max)())
8076
                {
8077
                    // str 16
8078
                    oa->write_character(static_cast<CharType>(0xDA));
8079
                    write_number(static_cast<uint16_t>(N));
8080
                }
8081
                else if (N <= (std::numeric_limits<uint32_t>::max)())
8082
                {
8083
                    // str 32
8084
                    oa->write_character(static_cast<CharType>(0xDB));
8085
                    write_number(static_cast<uint32_t>(N));
8086
                }
8087
8088
                // step 2: write the string
8089
                oa->write_characters(
8090
                    reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
8091
                    j.m_value.string->size());
8092
                break;
8093
            }
8094
8095
            case value_t::array:
8096
            {
8097
                // step 1: write control byte and the array size
8098
                const auto N = j.m_value.array->size();
8099
                if (N <= 15)
8100
                {
8101
                    // fixarray
8102
                    write_number(static_cast<uint8_t>(0x90 | N));
8103
                }
8104
                else if (N <= (std::numeric_limits<uint16_t>::max)())
8105
                {
8106
                    // array 16
8107
                    oa->write_character(static_cast<CharType>(0xDC));
8108
                    write_number(static_cast<uint16_t>(N));
8109
                }
8110
                else if (N <= (std::numeric_limits<uint32_t>::max)())
8111
                {
8112
                    // array 32
8113
                    oa->write_character(static_cast<CharType>(0xDD));
8114
                    write_number(static_cast<uint32_t>(N));
8115
                }
8116
8117
                // step 2: write each element
8118
                for (const auto& el : *j.m_value.array)
8119
                {
8120
                    write_msgpack(el);
8121
                }
8122
                break;
8123
            }
8124
8125
            case value_t::object:
8126
            {
8127
                // step 1: write control byte and the object size
8128
                const auto N = j.m_value.object->size();
8129
                if (N <= 15)
8130
                {
8131
                    // fixmap
8132
                    write_number(static_cast<uint8_t>(0x80 | (N & 0xF)));
8133
                }
8134
                else if (N <= (std::numeric_limits<uint16_t>::max)())
8135
                {
8136
                    // map 16
8137
                    oa->write_character(static_cast<CharType>(0xDE));
8138
                    write_number(static_cast<uint16_t>(N));
8139
                }
8140
                else if (N <= (std::numeric_limits<uint32_t>::max)())
8141
                {
8142
                    // map 32
8143
                    oa->write_character(static_cast<CharType>(0xDF));
8144
                    write_number(static_cast<uint32_t>(N));
8145
                }
8146
8147
                // step 2: write each element
8148
                for (const auto& el : *j.m_value.object)
8149
                {
8150
                    write_msgpack(el.first);
8151
                    write_msgpack(el.second);
8152
                }
8153
                break;
8154
            }
8155
8156
            default:
8157
                break;
8158
        }
8159
    }
8160
8161
    /*!
8162
    @param[in] j  JSON value to serialize
8163
    @param[in] use_count   whether to use '#' prefixes (optimized format)
8164
    @param[in] use_type    whether to use '$' prefixes (optimized format)
8165
    @param[in] add_prefix  whether prefixes need to be used for this value
8166
    */
8167
    void write_ubjson(const BasicJsonType& j, const bool use_count,
8168
                      const bool use_type, const bool add_prefix = true)
8169
    {
8170
        switch (j.type())
8171
        {
8172
            case value_t::null:
8173
            {
8174
                if (add_prefix)
8175
                {
8176
                    oa->write_character(static_cast<CharType>('Z'));
8177
                }
8178
                break;
8179
            }
8180
8181
            case value_t::boolean:
8182
            {
8183
                if (add_prefix)
8184
                    oa->write_character(j.m_value.boolean
8185
                                        ? static_cast<CharType>('T')
8186
                                        : static_cast<CharType>('F'));
8187
                break;
8188
            }
8189
8190
            case value_t::number_integer:
8191
            {
8192
                write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix);
8193
                break;
8194
            }
8195
8196
            case value_t::number_unsigned:
8197
            {
8198
                write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix);
8199
                break;
8200
            }
8201
8202
            case value_t::number_float:
8203
            {
8204
                write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix);
8205
                break;
8206
            }
8207
8208
            case value_t::string:
8209
            {
8210
                if (add_prefix)
8211
                {
8212
                    oa->write_character(static_cast<CharType>('S'));
8213
                }
8214
                write_number_with_ubjson_prefix(j.m_value.string->size(), true);
8215
                oa->write_characters(
8216
                    reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
8217
                    j.m_value.string->size());
8218
                break;
8219
            }
8220
8221
            case value_t::array:
8222
            {
8223
                if (add_prefix)
8224
                {
8225
                    oa->write_character(static_cast<CharType>('['));
8226
                }
8227
8228
                bool prefix_required = true;
8229
                if (use_type and not j.m_value.array->empty())
8230
                {
8231
                    assert(use_count);
8232
                    const CharType first_prefix = ubjson_prefix(j.front());
8233
                    const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
8234
                                                         [this, first_prefix](const BasicJsonType & v)
8235
                    {
8236
                        return ubjson_prefix(v) == first_prefix;
8237
                    });
8238
8239
                    if (same_prefix)
8240
                    {
8241
                        prefix_required = false;
8242
                        oa->write_character(static_cast<CharType>('$'));
8243
                        oa->write_character(first_prefix);
8244
                    }
8245
                }
8246
8247
                if (use_count)
8248
                {
8249
                    oa->write_character(static_cast<CharType>('#'));
8250
                    write_number_with_ubjson_prefix(j.m_value.array->size(), true);
8251
                }
8252
8253
                for (const auto& el : *j.m_value.array)
8254
                {
8255
                    write_ubjson(el, use_count, use_type, prefix_required);
8256
                }
8257
8258
                if (not use_count)
8259
                {
8260
                    oa->write_character(static_cast<CharType>(']'));
8261
                }
8262
8263
                break;
8264
            }
8265
8266
            case value_t::object:
8267
            {
8268
                if (add_prefix)
8269
                {
8270
                    oa->write_character(static_cast<CharType>('{'));
8271
                }
8272
8273
                bool prefix_required = true;
8274
                if (use_type and not j.m_value.object->empty())
8275
                {
8276
                    assert(use_count);
8277
                    const CharType first_prefix = ubjson_prefix(j.front());
8278
                    const bool same_prefix = std::all_of(j.begin(), j.end(),
8279
                                                         [this, first_prefix](const BasicJsonType & v)
8280
                    {
8281
                        return ubjson_prefix(v) == first_prefix;
8282
                    });
8283
8284
                    if (same_prefix)
8285
                    {
8286
                        prefix_required = false;
8287
                        oa->write_character(static_cast<CharType>('$'));
8288
                        oa->write_character(first_prefix);
8289
                    }
8290
                }
8291
8292
                if (use_count)
8293
                {
8294
                    oa->write_character(static_cast<CharType>('#'));
8295
                    write_number_with_ubjson_prefix(j.m_value.object->size(), true);
8296
                }
8297
8298
                for (const auto& el : *j.m_value.object)
8299
                {
8300
                    write_number_with_ubjson_prefix(el.first.size(), true);
8301
                    oa->write_characters(
8302
                        reinterpret_cast<const CharType*>(el.first.c_str()),
8303
                        el.first.size());
8304
                    write_ubjson(el.second, use_count, use_type, prefix_required);
8305
                }
8306
8307
                if (not use_count)
8308
                {
8309
                    oa->write_character(static_cast<CharType>('}'));
8310
                }
8311
8312
                break;
8313
            }
8314
8315
            default:
8316
                break;
8317
        }
8318
    }
8319
8320
  private:
8321
    /*
8322
    @brief write a number to output input
8323
8324
    @param[in] n number of type @a NumberType
8325
    @tparam NumberType the type of the number
8326
8327
    @note This function needs to respect the system's endianess, because bytes
8328
          in CBOR, MessagePack, and UBJSON are stored in network order (big
8329
          endian) and therefore need reordering on little endian systems.
8330
    */
8331
    template<typename NumberType>
8332
    void write_number(const NumberType n)
8333
    {
8334
        // step 1: write number to array of length NumberType
8335
        std::array<CharType, sizeof(NumberType)> vec;
8336
        std::memcpy(vec.data(), &n, sizeof(NumberType));
8337
8338
        // step 2: write array to output (with possible reordering)
8339
        if (is_little_endian)
8340
        {
8341
            // reverse byte order prior to conversion if necessary
8342
            std::reverse(vec.begin(), vec.end());
8343
        }
8344
8345
        oa->write_characters(vec.data(), sizeof(NumberType));
8346
    }
8347
8348
    // UBJSON: write number (floating point)
8349
    template<typename NumberType, typename std::enable_if<
8350
                 std::is_floating_point<NumberType>::value, int>::type = 0>
8351
    void write_number_with_ubjson_prefix(const NumberType n,
8352
                                         const bool add_prefix)
8353
    {
8354
        if (add_prefix)
8355
        {
8356
            oa->write_character(get_ubjson_float_prefix(n));
8357
        }
8358
        write_number(n);
8359
    }
8360
8361
    // UBJSON: write number (unsigned integer)
8362
    template<typename NumberType, typename std::enable_if<
8363
                 std::is_unsigned<NumberType>::value, int>::type = 0>
8364
    void write_number_with_ubjson_prefix(const NumberType n,
8365
                                         const bool add_prefix)
8366
    {
8367
        if (n <= static_cast<uint64_t>((std::numeric_limits<int8_t>::max)()))
8368
        {
8369
            if (add_prefix)
8370
            {
8371
                oa->write_character(static_cast<CharType>('i'));  // int8
8372
            }
8373
            write_number(static_cast<uint8_t>(n));
8374
        }
8375
        else if (n <= (std::numeric_limits<uint8_t>::max)())
8376
        {
8377
            if (add_prefix)
8378
            {
8379
                oa->write_character(static_cast<CharType>('U'));  // uint8
8380
            }
8381
            write_number(static_cast<uint8_t>(n));
8382
        }
8383
        else if (n <= static_cast<uint64_t>((std::numeric_limits<int16_t>::max)()))
8384
        {
8385
            if (add_prefix)
8386
            {
8387
                oa->write_character(static_cast<CharType>('I'));  // int16
8388
            }
8389
            write_number(static_cast<int16_t>(n));
8390
        }
8391
        else if (n <= static_cast<uint64_t>((std::numeric_limits<int32_t>::max)()))
8392
        {
8393
            if (add_prefix)
8394
            {
8395
                oa->write_character(static_cast<CharType>('l'));  // int32
8396
            }
8397
            write_number(static_cast<int32_t>(n));
8398
        }
8399
        else if (n <= static_cast<uint64_t>((std::numeric_limits<int64_t>::max)()))
8400
        {
8401
            if (add_prefix)
8402
            {
8403
                oa->write_character(static_cast<CharType>('L'));  // int64
8404
            }
8405
            write_number(static_cast<int64_t>(n));
8406
        }
8407
        else
8408
        {
8409
            JSON_THROW(out_of_range::create(407, "number overflow serializing " + std::to_string(n)));
8410
        }
8411
    }
8412
8413
    // UBJSON: write number (signed integer)
8414
    template<typename NumberType, typename std::enable_if<
8415
                 std::is_signed<NumberType>::value and
8416
                 not std::is_floating_point<NumberType>::value, int>::type = 0>
8417
    void write_number_with_ubjson_prefix(const NumberType n,
8418
                                         const bool add_prefix)
8419
    {
8420
        if ((std::numeric_limits<int8_t>::min)() <= n and n <= (std::numeric_limits<int8_t>::max)())
8421
        {
8422
            if (add_prefix)
8423
            {
8424
                oa->write_character(static_cast<CharType>('i'));  // int8
8425
            }
8426
            write_number(static_cast<int8_t>(n));
8427
        }
8428
        else if (static_cast<int64_t>((std::numeric_limits<uint8_t>::min)()) <= n and n <= static_cast<int64_t>((std::numeric_limits<uint8_t>::max)()))
8429
        {
8430
            if (add_prefix)
8431
            {
8432
                oa->write_character(static_cast<CharType>('U'));  // uint8
8433
            }
8434
            write_number(static_cast<uint8_t>(n));
8435
        }
8436
        else if ((std::numeric_limits<int16_t>::min)() <= n and n <= (std::numeric_limits<int16_t>::max)())
8437
        {
8438
            if (add_prefix)
8439
            {
8440
                oa->write_character(static_cast<CharType>('I'));  // int16
8441
            }
8442
            write_number(static_cast<int16_t>(n));
8443
        }
8444
        else if ((std::numeric_limits<int32_t>::min)() <= n and n <= (std::numeric_limits<int32_t>::max)())
8445
        {
8446
            if (add_prefix)
8447
            {
8448
                oa->write_character(static_cast<CharType>('l'));  // int32
8449
            }
8450
            write_number(static_cast<int32_t>(n));
8451
        }
8452
        else if ((std::numeric_limits<int64_t>::min)() <= n and n <= (std::numeric_limits<int64_t>::max)())
8453
        {
8454
            if (add_prefix)
8455
            {
8456
                oa->write_character(static_cast<CharType>('L'));  // int64
8457
            }
8458
            write_number(static_cast<int64_t>(n));
8459
        }
8460
        // LCOV_EXCL_START
8461
        else
8462
        {
8463
            JSON_THROW(out_of_range::create(407, "number overflow serializing " + std::to_string(n)));
8464
        }
8465
        // LCOV_EXCL_STOP
8466
    }
8467
8468
    /*!
8469
    @brief determine the type prefix of container values
8470
8471
    @note This function does not need to be 100% accurate when it comes to
8472
          integer limits. In case a number exceeds the limits of int64_t,
8473
          this will be detected by a later call to function
8474
          write_number_with_ubjson_prefix. Therefore, we return 'L' for any
8475
          value that does not fit the previous limits.
8476
    */
8477
    CharType ubjson_prefix(const BasicJsonType& j) const noexcept
8478
    {
8479
        switch (j.type())
8480
        {
8481
            case value_t::null:
8482
                return 'Z';
8483
8484
            case value_t::boolean:
8485
                return j.m_value.boolean ? 'T' : 'F';
8486
8487
            case value_t::number_integer:
8488
            {
8489
                if ((std::numeric_limits<int8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<int8_t>::max)())
8490
                {
8491
                    return 'i';
8492
                }
8493
                else if ((std::numeric_limits<uint8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<uint8_t>::max)())
8494
                {
8495
                    return 'U';
8496
                }
8497
                else if ((std::numeric_limits<int16_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<int16_t>::max)())
8498
                {
8499
                    return 'I';
8500
                }
8501
                else if ((std::numeric_limits<int32_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<int32_t>::max)())
8502
                {
8503
                    return 'l';
8504
                }
8505
                else  // no check and assume int64_t (see note above)
8506
                {
8507
                    return 'L';
8508
                }
8509
            }
8510
8511
            case value_t::number_unsigned:
8512
            {
8513
                if (j.m_value.number_unsigned <= (std::numeric_limits<int8_t>::max)())
8514
                {
8515
                    return 'i';
8516
                }
8517
                else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
8518
                {
8519
                    return 'U';
8520
                }
8521
                else if (j.m_value.number_unsigned <= (std::numeric_limits<int16_t>::max)())
8522
                {
8523
                    return 'I';
8524
                }
8525
                else if (j.m_value.number_unsigned <= (std::numeric_limits<int32_t>::max)())
8526
                {
8527
                    return 'l';
8528
                }
8529
                else  // no check and assume int64_t (see note above)
8530
                {
8531
                    return 'L';
8532
                }
8533
            }
8534
8535
            case value_t::number_float:
8536
                return get_ubjson_float_prefix(j.m_value.number_float);
8537
8538
            case value_t::string:
8539
                return 'S';
8540
8541
            case value_t::array:
8542
                return '[';
8543
8544
            case value_t::object:
8545
                return '{';
8546
8547
            default:  // discarded values
8548
                return 'N';
8549
        }
8550
    }
8551
8552
    static constexpr CharType get_cbor_float_prefix(float)
8553
    {
8554
        return static_cast<CharType>(0xFA);  // Single-Precision Float
8555
    }
8556
8557
    static constexpr CharType get_cbor_float_prefix(double)
8558
    {
8559
        return static_cast<CharType>(0xFB);  // Double-Precision Float
8560
    }
8561
8562
    static constexpr CharType get_msgpack_float_prefix(float)
8563
    {
8564
        return static_cast<CharType>(0xCA);  // float 32
8565
    }
8566
8567
    static constexpr CharType get_msgpack_float_prefix(double)
8568
    {
8569
        return static_cast<CharType>(0xCB);  // float 64
8570
    }
8571
8572
    static constexpr CharType get_ubjson_float_prefix(float)
8573
    {
8574
        return 'd';  // float 32
8575
    }
8576
8577
    static constexpr CharType get_ubjson_float_prefix(double)
8578
    {
8579
        return 'D';  // float 64
8580
    }
8581
8582
  private:
8583
    /// whether we can assume little endianess
8584
    const bool is_little_endian = binary_reader<BasicJsonType>::little_endianess();
8585
8586
    /// the output
8587
    output_adapter_t<CharType> oa = nullptr;
8588
};
8589
}
8590
}
8591
8592
// #include <nlohmann/detail/output/serializer.hpp>
8593
8594
8595
#include <algorithm> // reverse, remove, fill, find, none_of
8596
#include <array> // array
8597
#include <cassert> // assert
8598
#include <ciso646> // and, or
8599
#include <clocale> // localeconv, lconv
8600
#include <cmath> // labs, isfinite, isnan, signbit
8601
#include <cstddef> // size_t, ptrdiff_t
8602
#include <cstdint> // uint8_t
8603
#include <cstdio> // snprintf
8604
#include <limits> // numeric_limits
8605
#include <string> // string
8606
#include <type_traits> // is_same
8607
8608
// #include <nlohmann/detail/exceptions.hpp>
8609
8610
// #include <nlohmann/detail/conversions/to_chars.hpp>
8611
8612
8613
#include <cassert> // assert
8614
#include <ciso646> // or, and, not
8615
#include <cmath>   // signbit, isfinite
8616
#include <cstdint> // intN_t, uintN_t
8617
#include <cstring> // memcpy, memmove
8618
8619
namespace nlohmann
8620
{
8621
namespace detail
8622
{
8623
8624
/*!
8625
@brief implements the Grisu2 algorithm for binary to decimal floating-point
8626
conversion.
8627
8628
This implementation is a slightly modified version of the reference
8629
implementation which may be obtained from
8630
http://florian.loitsch.com/publications (bench.tar.gz).
8631
8632
The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch.
8633
8634
For a detailed description of the algorithm see:
8635
8636
[1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with
8637
    Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming
8638
    Language Design and Implementation, PLDI 2010
8639
[2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately",
8640
    Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language
8641
    Design and Implementation, PLDI 1996
8642
*/
8643
namespace dtoa_impl
8644
{
8645
8646
template <typename Target, typename Source>
8647
Target reinterpret_bits(const Source source)
8648
7
{
8649
7
    static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
8650
7
8651
7
    Target target;
8652
7
    std::memcpy(&target, &source, sizeof(Source));
8653
7
    return target;
8654
7
}
8655
8656
struct diyfp // f * 2^e
8657
{
8658
    static constexpr int kPrecision = 64; // = q
8659
8660
    uint64_t f;
8661
    int e;
8662
8663
0
    constexpr diyfp() noexcept : f(0), e(0) {}
8664
91
    constexpr diyfp(uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
8665
8666
    /*!
8667
    @brief returns x - y
8668
    @pre x.e == y.e and x.f >= y.f
8669
    */
8670
    static diyfp sub(const diyfp& x, const diyfp& y) noexcept
8671
14
    {
8672
14
        assert(x.e == y.e);
8673
14
        assert(x.f >= y.f);
8674
14
8675
14
        return diyfp(x.f - y.f, x.e);
8676
14
    }
8677
8678
    /*!
8679
    @brief returns x * y
8680
    @note The result is rounded. (Only the upper q bits are returned.)
8681
    */
8682
    static diyfp mul(const diyfp& x, const diyfp& y) noexcept
8683
21
    {
8684
21
        static_assert(kPrecision == 64, "internal error");
8685
21
8686
21
        // Computes:
8687
21
        //  f = round((x.f * y.f) / 2^q)
8688
21
        //  e = x.e + y.e + q
8689
21
8690
21
        // Emulate the 64-bit * 64-bit multiplication:
8691
21
        //
8692
21
        // p = u * v
8693
21
        //   = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
8694
21
        //   = (u_lo v_lo         ) + 2^32 ((u_lo v_hi         ) + (u_hi v_lo         )) + 2^64 (u_hi v_hi         )
8695
21
        //   = (p0                ) + 2^32 ((p1                ) + (p2                )) + 2^64 (p3                )
8696
21
        //   = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3                )
8697
21
        //   = (p0_lo             ) + 2^32 (p0_hi + p1_lo + p2_lo                      ) + 2^64 (p1_hi + p2_hi + p3)
8698
21
        //   = (p0_lo             ) + 2^32 (Q                                          ) + 2^64 (H                 )
8699
21
        //   = (p0_lo             ) + 2^32 (Q_lo + 2^32 Q_hi                           ) + 2^64 (H                 )
8700
21
        //
8701
21
        // (Since Q might be larger than 2^32 - 1)
8702
21
        //
8703
21
        //   = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
8704
21
        //
8705
21
        // (Q_hi + H does not overflow a 64-bit int)
8706
21
        //
8707
21
        //   = p_lo + 2^64 p_hi
8708
21
8709
21
        const uint64_t u_lo = x.f & 0xFFFFFFFF;
8710
21
        const uint64_t u_hi = x.f >> 32;
8711
21
        const uint64_t v_lo = y.f & 0xFFFFFFFF;
8712
21
        const uint64_t v_hi = y.f >> 32;
8713
21
8714
21
        const uint64_t p0 = u_lo * v_lo;
8715
21
        const uint64_t p1 = u_lo * v_hi;
8716
21
        const uint64_t p2 = u_hi * v_lo;
8717
21
        const uint64_t p3 = u_hi * v_hi;
8718
21
8719
21
        const uint64_t p0_hi = p0 >> 32;
8720
21
        const uint64_t p1_lo = p1 & 0xFFFFFFFF;
8721
21
        const uint64_t p1_hi = p1 >> 32;
8722
21
        const uint64_t p2_lo = p2 & 0xFFFFFFFF;
8723
21
        const uint64_t p2_hi = p2 >> 32;
8724
21
8725
21
        uint64_t Q = p0_hi + p1_lo + p2_lo;
8726
21
8727
21
        // The full product might now be computed as
8728
21
        //
8729
21
        // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
8730
21
        // p_lo = p0_lo + (Q << 32)
8731
21
        //
8732
21
        // But in this particular case here, the full p_lo is not required.
8733
21
        // Effectively we only need to add the highest bit in p_lo to p_hi (and
8734
21
        // Q_hi + 1 does not overflow).
8735
21
8736
21
        Q += uint64_t{1} << (64 - 32 - 1); // round, ties up
8737
21
8738
21
        const uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32);
8739
21
8740
21
        return diyfp(h, x.e + y.e + 64);
8741
21
    }
8742
8743
    /*!
8744
    @brief normalize x such that the significand is >= 2^(q-1)
8745
    @pre x.f != 0
8746
    */
8747
    static diyfp normalize(diyfp x) noexcept
8748
14
    {
8749
14
        assert(x.f != 0);
8750
14
8751
161
        while ((x.f >> 63) == 0)
8752
147
        {
8753
147
            x.f <<= 1;
8754
147
            x.e--;
8755
147
        }
8756
14
8757
14
        return x;
8758
14
    }
8759
8760
    /*!
8761
    @brief normalize x such that the result has the exponent E
8762
    @pre e >= x.e and the upper e - x.e bits of x.f must be zero.
8763
    */
8764
    static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
8765
7
    {
8766
7
        const int delta = x.e - target_exponent;
8767
7
8768
7
        assert(delta >= 0);
8769
7
        assert(((x.f << delta) >> delta) == x.f);
8770
7
8771
7
        return diyfp(x.f << delta, target_exponent);
8772
7
    }
8773
};
8774
8775
struct boundaries
8776
{
8777
    diyfp w;
8778
    diyfp minus;
8779
    diyfp plus;
8780
};
8781
8782
/*!
8783
Compute the (normalized) diyfp representing the input number 'value' and its
8784
boundaries.
8785
8786
@pre value must be finite and positive
8787
*/
8788
template <typename FloatType>
8789
boundaries compute_boundaries(FloatType value)
8790
7
{
8791
7
    assert(std::isfinite(value));
8792
7
    assert(value > 0);
8793
7
8794
7
    // Convert the IEEE representation into a diyfp.
8795
7
    //
8796
7
    // If v is denormal:
8797
7
    //      value = 0.F * 2^(1 - bias) = (          F) * 2^(1 - bias - (p-1))
8798
7
    // If v is normalized:
8799
7
    //      value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
8800
7
8801
7
    static_assert(std::numeric_limits<FloatType>::is_iec559,
8802
7
                  "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
8803
7
8804
7
    constexpr int      kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
8805
7
    constexpr int      kBias      = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
8806
7
    constexpr int      kMinExp    = 1 - kBias;
8807
7
    constexpr uint64_t kHiddenBit = uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
8808
7
8809
7
    using bits_type = typename std::conditional< kPrecision == 24, uint32_t, uint64_t >::type;
8810
7
8811
7
    const uint64_t bits = reinterpret_bits<bits_type>(value);
8812
7
    const uint64_t E = bits >> (kPrecision - 1);
8813
7
    const uint64_t F = bits & (kHiddenBit - 1);
8814
7
8815
7
    const bool is_denormal = (E == 0);
8816
7
    const diyfp v = is_denormal
8817
7
                    ? diyfp(F, kMinExp)
8818
7
                    : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
8819
7
8820
7
    // Compute the boundaries m- and m+ of the floating-point value
8821
7
    // v = f * 2^e.
8822
7
    //
8823
7
    // Determine v- and v+, the floating-point predecessor and successor if v,
8824
7
    // respectively.
8825
7
    //
8826
7
    //      v- = v - 2^e        if f != 2^(p-1) or e == e_min                (A)
8827
7
    //         = v - 2^(e-1)    if f == 2^(p-1) and e > e_min                (B)
8828
7
    //
8829
7
    //      v+ = v + 2^e
8830
7
    //
8831
7
    // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
8832
7
    // between m- and m+ round to v, regardless of how the input rounding
8833
7
    // algorithm breaks ties.
8834
7
    //
8835
7
    //      ---+-------------+-------------+-------------+-------------+---  (A)
8836
7
    //         v-            m-            v             m+            v+
8837
7
    //
8838
7
    //      -----------------+------+------+-------------+-------------+---  (B)
8839
7
    //                       v-     m-     v             m+            v+
8840
7
8841
7
    const bool lower_boundary_is_closer = (F == 0 and E > 1);
8842
7
    const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
8843
7
    const diyfp m_minus = lower_boundary_is_closer
8844
7
                          ? diyfp(4 * v.f - 1, v.e - 2)  // (B)
8845
7
                          : diyfp(2 * v.f - 1, v.e - 1); // (A)
8846
7
8847
7
    // Determine the normalized w+ = m+.
8848
7
    const diyfp w_plus = diyfp::normalize(m_plus);
8849
7
8850
7
    // Determine w- = m- such that e_(w-) = e_(w+).
8851
7
    const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
8852
7
8853
7
    return {diyfp::normalize(v), w_minus, w_plus};
8854
7
}
8855
8856
// Given normalized diyfp w, Grisu needs to find a (normalized) cached
8857
// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
8858
// within a certain range [alpha, gamma] (Definition 3.2 from [1])
8859
//
8860
//      alpha <= e = e_c + e_w + q <= gamma
8861
//
8862
// or
8863
//
8864
//      f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
8865
//                          <= f_c * f_w * 2^gamma
8866
//
8867
// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
8868
//
8869
//      2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
8870
//
8871
// or
8872
//
8873
//      2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
8874
//
8875
// The choice of (alpha,gamma) determines the size of the table and the form of
8876
// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
8877
// in practice:
8878
//
8879
// The idea is to cut the number c * w = f * 2^e into two parts, which can be
8880
// processed independently: An integral part p1, and a fractional part p2:
8881
//
8882
//      f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
8883
//              = (f div 2^-e) + (f mod 2^-e) * 2^e
8884
//              = p1 + p2 * 2^e
8885
//
8886
// The conversion of p1 into decimal form requires a series of divisions and
8887
// modulos by (a power of) 10. These operations are faster for 32-bit than for
8888
// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
8889
// achieved by choosing
8890
//
8891
//      -e >= 32   or   e <= -32 := gamma
8892
//
8893
// In order to convert the fractional part
8894
//
8895
//      p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
8896
//
8897
// into decimal form, the fraction is repeatedly multiplied by 10 and the digits
8898
// d[-i] are extracted in order:
8899
//
8900
//      (10 * p2) div 2^-e = d[-1]
8901
//      (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
8902
//
8903
// The multiplication by 10 must not overflow. It is sufficient to choose
8904
//
8905
//      10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
8906
//
8907
// Since p2 = f mod 2^-e < 2^-e,
8908
//
8909
//      -e <= 60   or   e >= -60 := alpha
8910
8911
constexpr int kAlpha = -60;
8912
constexpr int kGamma = -32;
8913
8914
struct cached_power // c = f * 2^e ~= 10^k
8915
{
8916
    uint64_t f;
8917
    int e;
8918
    int k;
8919
};
8920
8921
/*!
8922
For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached
8923
power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c
8924
satisfies (Definition 3.2 from [1])
8925
8926
     alpha <= e_c + e + q <= gamma.
8927
*/
8928
inline cached_power get_cached_power_for_binary_exponent(int e)
8929
7
{
8930
7
    // Now
8931
7
    //
8932
7
    //      alpha <= e_c + e + q <= gamma                                    (1)
8933
7
    //      ==> f_c * 2^alpha <= c * 2^e * 2^q
8934
7
    //
8935
7
    // and since the c's are normalized, 2^(q-1) <= f_c,
8936
7
    //
8937
7
    //      ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
8938
7
    //      ==> 2^(alpha - e - 1) <= c
8939
7
    //
8940
7
    // If c were an exakt power of ten, i.e. c = 10^k, one may determine k as
8941
7
    //
8942
7
    //      k = ceil( log_10( 2^(alpha - e - 1) ) )
8943
7
    //        = ceil( (alpha - e - 1) * log_10(2) )
8944
7
    //
8945
7
    // From the paper:
8946
7
    // "In theory the result of the procedure could be wrong since c is rounded,
8947
7
    //  and the computation itself is approximated [...]. In practice, however,
8948
7
    //  this simple function is sufficient."
8949
7
    //
8950
7
    // For IEEE double precision floating-point numbers converted into
8951
7
    // normalized diyfp's w = f * 2^e, with q = 64,
8952
7
    //
8953
7
    //      e >= -1022      (min IEEE exponent)
8954
7
    //           -52        (p - 1)
8955
7
    //           -52        (p - 1, possibly normalize denormal IEEE numbers)
8956
7
    //           -11        (normalize the diyfp)
8957
7
    //         = -1137
8958
7
    //
8959
7
    // and
8960
7
    //
8961
7
    //      e <= +1023      (max IEEE exponent)
8962
7
    //           -52        (p - 1)
8963
7
    //           -11        (normalize the diyfp)
8964
7
    //         = 960
8965
7
    //
8966
7
    // This binary exponent range [-1137,960] results in a decimal exponent
8967
7
    // range [-307,324]. One does not need to store a cached power for each
8968
7
    // k in this range. For each such k it suffices to find a cached power
8969
7
    // such that the exponent of the product lies in [alpha,gamma].
8970
7
    // This implies that the difference of the decimal exponents of adjacent
8971
7
    // table entries must be less than or equal to
8972
7
    //
8973
7
    //      floor( (gamma - alpha) * log_10(2) ) = 8.
8974
7
    //
8975
7
    // (A smaller distance gamma-alpha would require a larger table.)
8976
7
8977
7
    // NB:
8978
7
    // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
8979
7
8980
7
    constexpr int kCachedPowersSize = 79;
8981
7
    constexpr int kCachedPowersMinDecExp = -300;
8982
7
    constexpr int kCachedPowersDecStep = 8;
8983
7
8984
7
    static constexpr cached_power kCachedPowers[] =
8985
7
    {
8986
7
        { 0xAB70FE17C79AC6CA, -1060, -300 },
8987
7
        { 0xFF77B1FCBEBCDC4F, -1034, -292 },
8988
7
        { 0xBE5691EF416BD60C, -1007, -284 },
8989
7
        { 0x8DD01FAD907FFC3C,  -980, -276 },
8990
7
        { 0xD3515C2831559A83,  -954, -268 },
8991
7
        { 0x9D71AC8FADA6C9B5,  -927, -260 },
8992
7
        { 0xEA9C227723EE8BCB,  -901, -252 },
8993
7
        { 0xAECC49914078536D,  -874, -244 },
8994
7
        { 0x823C12795DB6CE57,  -847, -236 },
8995
7
        { 0xC21094364DFB5637,  -821, -228 },
8996
7
        { 0x9096EA6F3848984F,  -794, -220 },
8997
7
        { 0xD77485CB25823AC7,  -768, -212 },
8998
7
        { 0xA086CFCD97BF97F4,  -741, -204 },
8999
7
        { 0xEF340A98172AACE5,  -715, -196 },
9000
7
        { 0xB23867FB2A35B28E,  -688, -188 },
9001
7
        { 0x84C8D4DFD2C63F3B,  -661, -180 },
9002
7
        { 0xC5DD44271AD3CDBA,  -635, -172 },
9003
7
        { 0x936B9FCEBB25C996,  -608, -164 },
9004
7
        { 0xDBAC6C247D62A584,  -582, -156 },
9005
7
        { 0xA3AB66580D5FDAF6,  -555, -148 },
9006
7
        { 0xF3E2F893DEC3F126,  -529, -140 },
9007
7
        { 0xB5B5ADA8AAFF80B8,  -502, -132 },
9008
7
        { 0x87625F056C7C4A8B,  -475, -124 },
9009
7
        { 0xC9BCFF6034C13053,  -449, -116 },
9010
7
        { 0x964E858C91BA2655,  -422, -108 },
9011
7
        { 0xDFF9772470297EBD,  -396, -100 },
9012
7
        { 0xA6DFBD9FB8E5B88F,  -369,  -92 },
9013
7
        { 0xF8A95FCF88747D94,  -343,  -84 },
9014
7
        { 0xB94470938FA89BCF,  -316,  -76 },
9015
7
        { 0x8A08F0F8BF0F156B,  -289,  -68 },
9016
7
        { 0xCDB02555653131B6,  -263,  -60 },
9017
7
        { 0x993FE2C6D07B7FAC,  -236,  -52 },
9018
7
        { 0xE45C10C42A2B3B06,  -210,  -44 },
9019
7
        { 0xAA242499697392D3,  -183,  -36 },
9020
7
        { 0xFD87B5F28300CA0E,  -157,  -28 },
9021
7
        { 0xBCE5086492111AEB,  -130,  -20 },
9022
7
        { 0x8CBCCC096F5088CC,  -103,  -12 },
9023
7
        { 0xD1B71758E219652C,   -77,   -4 },
9024
7
        { 0x9C40000000000000,   -50,    4 },
9025
7
        { 0xE8D4A51000000000,   -24,   12 },
9026
7
        { 0xAD78EBC5AC620000,     3,   20 },
9027
7
        { 0x813F3978F8940984,    30,   28 },
9028
7
        { 0xC097CE7BC90715B3,    56,   36 },
9029
7
        { 0x8F7E32CE7BEA5C70,    83,   44 },
9030
7
        { 0xD5D238A4ABE98068,   109,   52 },
9031
7
        { 0x9F4F2726179A2245,   136,   60 },
9032
7
        { 0xED63A231D4C4FB27,   162,   68 },
9033
7
        { 0xB0DE65388CC8ADA8,   189,   76 },
9034
7
        { 0x83C7088E1AAB65DB,   216,   84 },
9035
7
        { 0xC45D1DF942711D9A,   242,   92 },
9036
7
        { 0x924D692CA61BE758,   269,  100 },
9037
7
        { 0xDA01EE641A708DEA,   295,  108 },
9038
7
        { 0xA26DA3999AEF774A,   322,  116 },
9039
7
        { 0xF209787BB47D6B85,   348,  124 },
9040
7
        { 0xB454E4A179DD1877,   375,  132 },
9041
7
        { 0x865B86925B9BC5C2,   402,  140 },
9042
7
        { 0xC83553C5C8965D3D,   428,  148 },
9043
7
        { 0x952AB45CFA97A0B3,   455,  156 },
9044
7
        { 0xDE469FBD99A05FE3,   481,  164 },
9045
7
        { 0xA59BC234DB398C25,   508,  172 },
9046
7
        { 0xF6C69A72A3989F5C,   534,  180 },
9047
7
        { 0xB7DCBF5354E9BECE,   561,  188 },
9048
7
        { 0x88FCF317F22241E2,   588,  196 },
9049
7
        { 0xCC20CE9BD35C78A5,   614,  204 },
9050
7
        { 0x98165AF37B2153DF,   641,  212 },
9051
7
        { 0xE2A0B5DC971F303A,   667,  220 },
9052
7
        { 0xA8D9D1535CE3B396,   694,  228 },
9053
7
        { 0xFB9B7CD9A4A7443C,   720,  236 },
9054
7
        { 0xBB764C4CA7A44410,   747,  244 },
9055
7
        { 0x8BAB8EEFB6409C1A,   774,  252 },
9056
7
        { 0xD01FEF10A657842C,   800,  260 },
9057
7
        { 0x9B10A4E5E9913129,   827,  268 },
9058
7
        { 0xE7109BFBA19C0C9D,   853,  276 },
9059
7
        { 0xAC2820D9623BF429,   880,  284 },
9060
7
        { 0x80444B5E7AA7CF85,   907,  292 },
9061
7
        { 0xBF21E44003ACDD2D,   933,  300 },
9062
7
        { 0x8E679C2F5E44FF8F,   960,  308 },
9063
7
        { 0xD433179D9C8CB841,   986,  316 },
9064
7
        { 0x9E19DB92B4E31BA9,  1013,  324 },
9065
7
    };
9066
7
9067
7
    // This computation gives exactly the same results for k as
9068
7
    //      k = ceil((kAlpha - e - 1) * 0.30102999566398114)
9069
7
    // for |e| <= 1500, but doesn't require floating-point operations.
9070
7
    // NB: log_10(2) ~= 78913 / 2^18
9071
7
    assert(e >= -1500);
9072
7
    assert(e <=  1500);
9073
7
    const int f = kAlpha - e - 1;
9074
7
    const int k = (f * 78913) / (1 << 18) + (f > 0);
9075
7
9076
7
    const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
9077
7
    assert(index >= 0);
9078
7
    assert(index < kCachedPowersSize);
9079
7
    static_cast<void>(kCachedPowersSize); // Fix warning.
9080
7
9081
7
    const cached_power cached = kCachedPowers[index];
9082
7
    assert(kAlpha <= cached.e + e + 64);
9083
7
    assert(kGamma >= cached.e + e + 64);
9084
7
9085
7
    return cached;
9086
7
}
9087
9088
/*!
9089
For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k.
9090
For n == 0, returns 1 and sets pow10 := 1.
9091
*/
9092
inline int find_largest_pow10(const uint32_t n, uint32_t& pow10)
9093
7
{
9094
7
    // LCOV_EXCL_START
9095
7
    if (n >= 1000000000)
9096
7
    {
9097
0
        pow10 = 1000000000;
9098
0
        return 10;
9099
0
    }
9100
7
    // LCOV_EXCL_STOP
9101
7
    else if (n >= 100000000)
9102
7
    {
9103
0
        pow10 = 100000000;
9104
0
        return  9;
9105
0
    }
9106
7
    else if (n >= 10000000)
9107
7
    {
9108
0
        pow10 = 10000000;
9109
0
        return  8;
9110
0
    }
9111
7
    else if (n >= 1000000)
9112
7
    {
9113
0
        pow10 = 1000000;
9114
0
        return  7;
9115
0
    }
9116
7
    else if (n >= 100000)
9117
7
    {
9118
6
        pow10 = 100000;
9119
6
        return  6;
9120
6
    }
9121
7
    else if (n >= 10000)
9122
1
    {
9123
1
        pow10 = 10000;
9124
1
        return  5;
9125
1
    }
9126
1
    else if (n >= 1000)
9127
0
    {
9128
0
        pow10 = 1000;
9129
0
        return  4;
9130
0
    }
9131
0
    else if (n >= 100)
9132
0
    {
9133
0
        pow10 = 100;
9134
0
        return  3;
9135
0
    }
9136
0
    else if (n >= 10)
9137
0
    {
9138
0
        pow10 = 10;
9139
0
        return  2;
9140
0
    }
9141
0
    else
9142
0
    {
9143
0
        pow10 = 1;
9144
0
        return 1;
9145
0
    }
9146
7
}
9147
9148
inline void grisu2_round(char* buf, int len, uint64_t dist, uint64_t delta,
9149
                         uint64_t rest, uint64_t ten_k)
9150
7
{
9151
7
    assert(len >= 1);
9152
7
    assert(dist <= delta);
9153
7
    assert(rest <= delta);
9154
7
    assert(ten_k > 0);
9155
7
9156
7
    //               <--------------------------- delta ---->
9157
7
    //                                  <---- dist --------->
9158
7
    // --------------[------------------+-------------------]--------------
9159
7
    //               M-                 w                   M+
9160
7
    //
9161
7
    //                                  ten_k
9162
7
    //                                <------>
9163
7
    //                                       <---- rest ---->
9164
7
    // --------------[------------------+----+--------------]--------------
9165
7
    //                                  w    V
9166
7
    //                                       = buf * 10^k
9167
7
    //
9168
7
    // ten_k represents a unit-in-the-last-place in the decimal representation
9169
7
    // stored in buf.
9170
7
    // Decrement buf by ten_k while this takes buf closer to w.
9171
7
9172
7
    // The tests are written in this order to avoid overflow in unsigned
9173
7
    // integer arithmetic.
9174
7
9175
7
    while (rest < dist
9176
7
            and delta - rest >= ten_k
9177
7
            and (rest + ten_k < dist or dist - rest > rest + ten_k - dist))
9178
7
    {
9179
0
        assert(buf[len - 1] != '0');
9180
0
        buf[len - 1]--;
9181
0
        rest += ten_k;
9182
0
    }
9183
7
}
9184
9185
/*!
9186
Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+.
9187
M- and M+ must be normalized and share the same exponent -60 <= e <= -32.
9188
*/
9189
inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
9190
                             diyfp M_minus, diyfp w, diyfp M_plus)
9191
7
{
9192
7
    static_assert(kAlpha >= -60, "internal error");
9193
7
    static_assert(kGamma <= -32, "internal error");
9194
7
9195
7
    // Generates the digits (and the exponent) of a decimal floating-point
9196
7
    // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
9197
7
    // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
9198
7
    //
9199
7
    //               <--------------------------- delta ---->
9200
7
    //                                  <---- dist --------->
9201
7
    // --------------[------------------+-------------------]--------------
9202
7
    //               M-                 w                   M+
9203
7
    //
9204
7
    // Grisu2 generates the digits of M+ from left to right and stops as soon as
9205
7
    // V is in [M-,M+].
9206
7
9207
7
    assert(M_plus.e >= kAlpha);
9208
7
    assert(M_plus.e <= kGamma);
9209
7
9210
7
    uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
9211
7
    uint64_t dist  = diyfp::sub(M_plus, w      ).f; // (significand of (M+ - w ), implicit exponent is e)
9212
7
9213
7
    // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
9214
7
    //
9215
7
    //      M+ = f * 2^e
9216
7
    //         = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
9217
7
    //         = ((p1        ) * 2^-e + (p2        )) * 2^e
9218
7
    //         = p1 + p2 * 2^e
9219
7
9220
7
    const diyfp one(uint64_t{1} << -M_plus.e, M_plus.e);
9221
7
9222
7
    uint32_t p1 = static_cast<uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
9223
7
    uint64_t p2 = M_plus.f & (one.f - 1);                    // p2 = f mod 2^-e
9224
7
9225
7
    // 1)
9226
7
    //
9227
7
    // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
9228
7
9229
7
    assert(p1 > 0);
9230
7
9231
7
    uint32_t pow10;
9232
7
    const int k = find_largest_pow10(p1, pow10);
9233
7
9234
7
    //      10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
9235
7
    //
9236
7
    //      p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
9237
7
    //         = (d[k-1]         ) * 10^(k-1) + (p1 mod 10^(k-1))
9238
7
    //
9239
7
    //      M+ = p1                                             + p2 * 2^e
9240
7
    //         = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1))          + p2 * 2^e
9241
7
    //         = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
9242
7
    //         = d[k-1] * 10^(k-1) + (                         rest) * 2^e
9243
7
    //
9244
7
    // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
9245
7
    //
9246
7
    //      p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
9247
7
    //
9248
7
    // but stop as soon as
9249
7
    //
9250
7
    //      rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
9251
7
9252
7
    int n = k;
9253
41
    while (n > 0)
9254
37
    {
9255
37
        // Invariants:
9256
37
        //      M+ = buffer * 10^n + (p1 + p2 * 2^e)    (buffer = 0 for n = k)
9257
37
        //      pow10 = 10^(n-1) <= p1 < 10^n
9258
37
        //
9259
37
        const uint32_t d = p1 / pow10;  // d = p1 div 10^(n-1)
9260
37
        const uint32_t r = p1 % pow10;  // r = p1 mod 10^(n-1)
9261
37
        //
9262
37
        //      M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
9263
37
        //         = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
9264
37
        //
9265
37
        assert(d <= 9);
9266
37
        buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
9267
37
        //
9268
37
        //      M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
9269
37
        //
9270
37
        p1 = r;
9271
37
        n--;
9272
37
        //
9273
37
        //      M+ = buffer * 10^n + (p1 + p2 * 2^e)
9274
37
        //      pow10 = 10^n
9275
37
        //
9276
37
9277
37
        // Now check if enough digits have been generated.
9278
37
        // Compute
9279
37
        //
9280
37
        //      p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
9281
37
        //
9282
37
        // Note:
9283
37
        // Since rest and delta share the same exponent e, it suffices to
9284
37
        // compare the significands.
9285
37
        const uint64_t rest = (uint64_t{p1} << -one.e) + p2;
9286
37
        if (rest <= delta)
9287
37
        {
9288
3
            // V = buffer * 10^n, with M- <= V <= M+.
9289
3
9290
3
            decimal_exponent += n;
9291
3
9292
3
            // We may now just stop. But instead look if the buffer could be
9293
3
            // decremented to bring V closer to w.
9294
3
            //
9295
3
            // pow10 = 10^n is now 1 ulp in the decimal representation V.
9296
3
            // The rounding procedure works with diyfp's with an implicit
9297
3
            // exponent of e.
9298
3
            //
9299
3
            //      10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
9300
3
            //
9301
3
            const uint64_t ten_n = uint64_t{pow10} << -one.e;
9302
3
            grisu2_round(buffer, length, dist, delta, rest, ten_n);
9303
3
9304
3
            return;
9305
3
        }
9306
37
9307
37
        pow10 /= 10;
9308
34
        //
9309
34
        //      pow10 = 10^(n-1) <= p1 < 10^n
9310
34
        // Invariants restored.
9311
34
    }
9312
7
9313
7
    // 2)
9314
7
    //
9315
7
    // The digits of the integral part have been generated:
9316
7
    //
9317
7
    //      M+ = d[k-1]...d[1]d[0] + p2 * 2^e
9318
7
    //         = buffer            + p2 * 2^e
9319
7
    //
9320
7
    // Now generate the digits of the fractional part p2 * 2^e.
9321
7
    //
9322
7
    // Note:
9323
7
    // No decimal point is generated: the exponent is adjusted instead.
9324
7
    //
9325
7
    // p2 actually represents the fraction
9326
7
    //
9327
7
    //      p2 * 2^e
9328
7
    //          = p2 / 2^-e
9329
7
    //          = d[-1] / 10^1 + d[-2] / 10^2 + ...
9330
7
    //
9331
7
    // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
9332
7
    //
9333
7
    //      p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
9334
7
    //                      + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
9335
7
    //
9336
7
    // using
9337
7
    //
9338
7
    //      10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
9339
7
    //                = (                   d) * 2^-e + (                   r)
9340
7
    //
9341
7
    // or
9342
7
    //      10^m * p2 * 2^e = d + r * 2^e
9343
7
    //
9344
7
    // i.e.
9345
7
    //
9346
7
    //      M+ = buffer + p2 * 2^e
9347
7
    //         = buffer + 10^-m * (d + r * 2^e)
9348
7
    //         = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
9349
7
    //
9350
7
    // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
9351
7
9352
7
    assert(p2 > delta);
9353
4
9354
4
    int m = 0;
9355
4
    for (;;)
9356
4
    {
9357
4
        // Invariant:
9358
4
        //      M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
9359
4
        //         = buffer * 10^-m + 10^-m * (p2                                 ) * 2^e
9360
4
        //         = buffer * 10^-m + 10^-m * (1/10 * (10 * p2)                   ) * 2^e
9361
4
        //         = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
9362
4
        //
9363
4
        assert(p2 <= UINT64_MAX / 10);
9364
4
        p2 *= 10;
9365
4
        const uint64_t d = p2 >> -one.e;     // d = (10 * p2) div 2^-e
9366
4
        const uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
9367
4
        //
9368
4
        //      M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
9369
4
        //         = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
9370
4
        //         = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
9371
4
        //
9372
4
        assert(d <= 9);
9373
4
        buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
9374
4
        //
9375
4
        //      M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
9376
4
        //
9377
4
        p2 = r;
9378
4
        m++;
9379
4
        //
9380
4
        //      M+ = buffer * 10^-m + 10^-m * p2 * 2^e
9381
4
        // Invariant restored.
9382
4
9383
4
        // Check if enough digits have been generated.
9384
4
        //
9385
4
        //      10^-m * p2 * 2^e <= delta * 2^e
9386
4
        //              p2 * 2^e <= 10^m * delta * 2^e
9387
4
        //                    p2 <= 10^m * delta
9388
4
        delta *= 10;
9389
4
        dist  *= 10;
9390
4
        if (p2 <= delta)
9391
4
        {
9392
4
            break;
9393
4
        }
9394
4
    }
9395
4
9396
4
    // V = buffer * 10^-m, with M- <= V <= M+.
9397
4
9398
4
    decimal_exponent -= m;
9399
4
9400
4
    // 1 ulp in the decimal representation is now 10^-m.
9401
4
    // Since delta and dist are now scaled by 10^m, we need to do the
9402
4
    // same with ulp in order to keep the units in sync.
9403
4
    //
9404
4
    //      10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
9405
4
    //
9406
4
    const uint64_t ten_m = one.f;
9407
4
    grisu2_round(buffer, length, dist, delta, p2, ten_m);
9408
4
9409
4
    // By construction this algorithm generates the shortest possible decimal
9410
4
    // number (Loitsch, Theorem 6.2) which rounds back to w.
9411
4
    // For an input number of precision p, at least
9412
4
    //
9413
4
    //      N = 1 + ceil(p * log_10(2))
9414
4
    //
9415
4
    // decimal digits are sufficient to identify all binary floating-point
9416
4
    // numbers (Matula, "In-and-Out conversions").
9417
4
    // This implies that the algorithm does not produce more than N decimal
9418
4
    // digits.
9419
4
    //
9420
4
    //      N = 17 for p = 53 (IEEE double precision)
9421
4
    //      N = 9  for p = 24 (IEEE single precision)
9422
4
}
9423
9424
/*!
9425
v = buf * 10^decimal_exponent
9426
len is the length of the buffer (number of decimal digits)
9427
The buffer must be large enough, i.e. >= max_digits10.
9428
*/
9429
inline void grisu2(char* buf, int& len, int& decimal_exponent,
9430
                   diyfp m_minus, diyfp v, diyfp m_plus)
9431
7
{
9432
7
    assert(m_plus.e == m_minus.e);
9433
7
    assert(m_plus.e == v.e);
9434
7
9435
7
    //  --------(-----------------------+-----------------------)--------    (A)
9436
7
    //          m-                      v                       m+
9437
7
    //
9438
7
    //  --------------------(-----------+-----------------------)--------    (B)
9439
7
    //                      m-          v                       m+
9440
7
    //
9441
7
    // First scale v (and m- and m+) such that the exponent is in the range
9442
7
    // [alpha, gamma].
9443
7
9444
7
    const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
9445
7
9446
7
    const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
9447
7
9448
7
    // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
9449
7
    const diyfp w       = diyfp::mul(v,       c_minus_k);
9450
7
    const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
9451
7
    const diyfp w_plus  = diyfp::mul(m_plus,  c_minus_k);
9452
7
9453
7
    //  ----(---+---)---------------(---+---)---------------(---+---)----
9454
7
    //          w-                      w                       w+
9455
7
    //          = c*m-                  = c*v                   = c*m+
9456
7
    //
9457
7
    // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
9458
7
    // w+ are now off by a small amount.
9459
7
    // In fact:
9460
7
    //
9461
7
    //      w - v * 10^k < 1 ulp
9462
7
    //
9463
7
    // To account for this inaccuracy, add resp. subtract 1 ulp.
9464
7
    //
9465
7
    //  --------+---[---------------(---+---)---------------]---+--------
9466
7
    //          w-  M-                  w                   M+  w+
9467
7
    //
9468
7
    // Now any number in [M-, M+] (bounds included) will round to w when input,
9469
7
    // regardless of how the input rounding algorithm breaks ties.
9470
7
    //
9471
7
    // And digit_gen generates the shortest possible such number in [M-, M+].
9472
7
    // Note that this does not mean that Grisu2 always generates the shortest
9473
7
    // possible number in the interval (m-, m+).
9474
7
    const diyfp M_minus(w_minus.f + 1, w_minus.e);
9475
7
    const diyfp M_plus (w_plus.f  - 1, w_plus.e );
9476
7
9477
7
    decimal_exponent = -cached.k; // = -(-k) = k
9478
7
9479
7
    grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
9480
7
}
9481
9482
/*!
9483
v = buf * 10^decimal_exponent
9484
len is the length of the buffer (number of decimal digits)
9485
The buffer must be large enough, i.e. >= max_digits10.
9486
*/
9487
template <typename FloatType>
9488
void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
9489
7
{
9490
7
    static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
9491
7
                  "internal error: not enough precision");
9492
7
9493
7
    assert(std::isfinite(value));
9494
7
    assert(value > 0);
9495
7
9496
7
    // If the neighbors (and boundaries) of 'value' are always computed for double-precision
9497
7
    // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
9498
7
    // decimal representations are not exactly "short".
9499
7
    //
9500
7
    // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
9501
7
    // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
9502
7
    // and since sprintf promotes float's to double's, I think this is exactly what 'std::to_chars'
9503
7
    // does.
9504
7
    // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
9505
7
    // representation using the corresponding std::from_chars function recovers value exactly". That
9506
7
    // indicates that single precision floating-point numbers should be recovered using
9507
7
    // 'std::strtof'.
9508
7
    //
9509
7
    // NB: If the neighbors are computed for single-precision numbers, there is a single float
9510
7
    //     (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
9511
7
    //     value is off by 1 ulp.
9512
#if 0
9513
    const boundaries w = compute_boundaries(static_cast<double>(value));
9514
#else
9515
7
    const boundaries w = compute_boundaries(value);
9516
7
#endif
9517
7
9518
7
    grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
9519
7
}
9520
9521
/*!
9522
@brief appends a decimal representation of e to buf
9523
@return a pointer to the element following the exponent.
9524
@pre -1000 < e < 1000
9525
*/
9526
inline char* append_exponent(char* buf, int e)
9527
0
{
9528
0
    assert(e > -1000);
9529
0
    assert(e <  1000);
9530
0
9531
0
    if (e < 0)
9532
0
    {
9533
0
        e = -e;
9534
0
        *buf++ = '-';
9535
0
    }
9536
0
    else
9537
0
    {
9538
0
        *buf++ = '+';
9539
0
    }
9540
0
9541
0
    uint32_t k = static_cast<uint32_t>(e);
9542
0
    if (k < 10)
9543
0
    {
9544
0
        // Always print at least two digits in the exponent.
9545
0
        // This is for compatibility with printf("%g").
9546
0
        *buf++ = '0';
9547
0
        *buf++ = static_cast<char>('0' + k);
9548
0
    }
9549
0
    else if (k < 100)
9550
0
    {
9551
0
        *buf++ = static_cast<char>('0' + k / 10);
9552
0
        k %= 10;
9553
0
        *buf++ = static_cast<char>('0' + k);
9554
0
    }
9555
0
    else
9556
0
    {
9557
0
        *buf++ = static_cast<char>('0' + k / 100);
9558
0
        k %= 100;
9559
0
        *buf++ = static_cast<char>('0' + k / 10);
9560
0
        k %= 10;
9561
0
        *buf++ = static_cast<char>('0' + k);
9562
0
    }
9563
0
9564
0
    return buf;
9565
0
}
9566
9567
/*!
9568
@brief prettify v = buf * 10^decimal_exponent
9569
9570
If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point
9571
notation. Otherwise it will be printed in exponential notation.
9572
9573
@pre min_exp < 0
9574
@pre max_exp > 0
9575
*/
9576
inline char* format_buffer(char* buf, int len, int decimal_exponent,
9577
                           int min_exp, int max_exp)
9578
7
{
9579
7
    assert(min_exp < 0);
9580
7
    assert(max_exp > 0);
9581
7
9582
7
    const int k = len;
9583
7
    const int n = len + decimal_exponent;
9584
7
9585
7
    // v = buf * 10^(n-k)
9586
7
    // k is the length of the buffer (number of decimal digits)
9587
7
    // n is the position of the decimal point relative to the start of the buffer.
9588
7
9589
7
    if (k <= n and n <= max_exp)
9590
7
    {
9591
0
        // digits[000]
9592
0
        // len <= max_exp + 2
9593
0
9594
0
        std::memset(buf + k, '0', static_cast<size_t>(n - k));
9595
0
        // Make it look like a floating-point number (#362, #378)
9596
0
        buf[n + 0] = '.';
9597
0
        buf[n + 1] = '0';
9598
0
        return buf + (n + 2);
9599
0
    }
9600
7
9601
7
    if (0 < n and n <= max_exp)
9602
7
    {
9603
7
        // dig.its
9604
7
        // len <= max_digits10 + 1
9605
7
9606
7
        assert(k > n);
9607
7
9608
7
        std::memmove(buf + (n + 1), buf + n, static_cast<size_t>(k - n));
9609
7
        buf[n] = '.';
9610
7
        return buf + (k + 1);
9611
7
    }
9612
7
9613
7
    if (min_exp < n and n <= 0)
9614
0
    {
9615
0
        // 0.[000]digits
9616
0
        // len <= 2 + (-min_exp - 1) + max_digits10
9617
0
9618
0
        std::memmove(buf + (2 + -n), buf, static_cast<size_t>(k));
9619
0
        buf[0] = '0';
9620
0
        buf[1] = '.';
9621
0
        std::memset(buf + 2, '0', static_cast<size_t>(-n));
9622
0
        return buf + (2 + (-n) + k);
9623
0
    }
9624
0
9625
0
    if (k == 1)
9626
0
    {
9627
0
        // dE+123
9628
0
        // len <= 1 + 5
9629
0
9630
0
        buf += 1;
9631
0
    }
9632
0
    else
9633
0
    {
9634
0
        // d.igitsE+123
9635
0
        // len <= max_digits10 + 1 + 5
9636
0
9637
0
        std::memmove(buf + 2, buf + 1, static_cast<size_t>(k - 1));
9638
0
        buf[1] = '.';
9639
0
        buf += 1 + k;
9640
0
    }
9641
0
9642
0
    *buf++ = 'e';
9643
0
    return append_exponent(buf, n - 1);
9644
0
}
9645
9646
} // namespace dtoa_impl
9647
9648
/*!
9649
@brief generates a decimal representation of the floating-point number value in [first, last).
9650
9651
The format of the resulting decimal representation is similar to printf's %g
9652
format. Returns an iterator pointing past-the-end of the decimal representation.
9653
9654
@note The input number must be finite, i.e. NaN's and Inf's are not supported.
9655
@note The buffer must be large enough.
9656
@note The result is NOT null-terminated.
9657
*/
9658
template <typename FloatType>
9659
char* to_chars(char* first, char* last, FloatType value)
9660
7
{
9661
7
    static_cast<void>(last); // maybe unused - fix warning
9662
7
    assert(std::isfinite(value));
9663
7
9664
7
    // Use signbit(value) instead of (value < 0) since signbit works for -0.
9665
7
    if (std::signbit(value))
9666
7
    {
9667
0
        value = -value;
9668
0
        *first++ = '-';
9669
0
    }
9670
7
9671
7
    if (value == 0) // +-0
9672
7
    {
9673
0
        *first++ = '0';
9674
0
        // Make it look like a floating-point number (#362, #378)
9675
0
        *first++ = '.';
9676
0
        *first++ = '0';
9677
0
        return first;
9678
0
    }
9679
7
9680
7
    assert(last - first >= std::numeric_limits<FloatType>::max_digits10);
9681
7
9682
7
    // Compute v = buffer * 10^decimal_exponent.
9683
7
    // The decimal digits are stored in the buffer, which needs to be interpreted
9684
7
    // as an unsigned decimal integer.
9685
7
    // len is the length of the buffer, i.e. the number of decimal digits.
9686
7
    int len = 0;
9687
7
    int decimal_exponent = 0;
9688
7
    dtoa_impl::grisu2(first, len, decimal_exponent, value);
9689
7
9690
7
    assert(len <= std::numeric_limits<FloatType>::max_digits10);
9691
7
9692
7
    // Format the buffer like printf("%.*g", prec, value)
9693
7
    constexpr int kMinExp = -4;
9694
7
    // Use digits10 here to increase compatibility with version 2.
9695
7
    constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
9696
7
9697
7
    assert(last - first >= kMaxExp + 2);
9698
7
    assert(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
9699
7
    assert(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
9700
7
9701
7
    return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
9702
7
}
9703
9704
} // namespace detail
9705
} // namespace nlohmann
9706
9707
// #include <nlohmann/detail/macro_scope.hpp>
9708
9709
// #include <nlohmann/detail/meta/cpp_future.hpp>
9710
9711
// #include <nlohmann/detail/output/output_adapters.hpp>
9712
9713
// #include <nlohmann/detail/value_t.hpp>
9714
9715
9716
namespace nlohmann
9717
{
9718
namespace detail
9719
{
9720
///////////////////
9721
// serialization //
9722
///////////////////
9723
9724
template<typename BasicJsonType>
9725
class serializer
9726
{
9727
    using string_t = typename BasicJsonType::string_t;
9728
    using number_float_t = typename BasicJsonType::number_float_t;
9729
    using number_integer_t = typename BasicJsonType::number_integer_t;
9730
    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9731
    static constexpr uint8_t UTF8_ACCEPT = 0;
9732
    static constexpr uint8_t UTF8_REJECT = 1;
9733
9734
  public:
9735
    /*!
9736
    @param[in] s  output stream to serialize to
9737
    @param[in] ichar  indentation character to use
9738
    */
9739
    serializer(output_adapter_t<char> s, const char ichar)
9740
        : o(std::move(s)), loc(std::localeconv()),
9741
          thousands_sep(loc->thousands_sep == nullptr ? '\0' : * (loc->thousands_sep)),
9742
          decimal_point(loc->decimal_point == nullptr ? '\0' : * (loc->decimal_point)),
9743
          indent_char(ichar), indent_string(512, indent_char)
9744
122
    {}
9745
9746
    // delete because of pointer members
9747
    serializer(const serializer&) = delete;
9748
    serializer& operator=(const serializer&) = delete;
9749
9750
    /*!
9751
    @brief internal implementation of the serialization function
9752
9753
    This function is called by the public member function dump and organizes
9754
    the serialization internally. The indentation level is propagated as
9755
    additional parameter. In case of arrays and objects, the function is
9756
    called recursively.
9757
9758
    - strings and object keys are escaped using `escape_string()`
9759
    - integer numbers are converted implicitly via `operator<<`
9760
    - floating-point numbers are converted to a string using `"%g"` format
9761
9762
    @param[in] val             value to serialize
9763
    @param[in] pretty_print    whether the output shall be pretty-printed
9764
    @param[in] indent_step     the indent level
9765
    @param[in] current_indent  the current indent level (only used internally)
9766
    */
9767
    void dump(const BasicJsonType& val, const bool pretty_print,
9768
              const bool ensure_ascii,
9769
              const unsigned int indent_step,
9770
              const unsigned int current_indent = 0)
9771
2.59k
    {
9772
2.59k
        switch (val.m_type)
9773
0
        {
9774
597
            case value_t::object:
9775
597
            {
9776
597
                if (val.m_value.object->empty())
9777
597
                {
9778
0
                    o->write_characters("{}", 2);
9779
0
                    return;
9780
0
                }
9781
597
9782
597
                if (pretty_print)
9783
597
                {
9784
360
                    o->write_characters("{\n", 2);
9785
360
9786
360
                    // variable to hold indentation for recursive calls
9787
360
                    const auto new_indent = current_indent + indent_step;
9788
360
                    if (JSON_UNLIKELY(indent_string.size() < new_indent))
9789
360
                    {
9790
0
                        indent_string.resize(indent_string.size() * 2, ' ');
9791
0
                    }
9792
360
9793
360
                    // first n-1 elements
9794
360
                    auto i = val.m_value.object->cbegin();
9795
1.67k
                    for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
9796
1.31k
                    {
9797
1.31k
                        o->write_characters(indent_string.c_str(), new_indent);
9798
1.31k
                        o->write_character('\"');
9799
1.31k
                        dump_escaped(i->first, ensure_ascii);
9800
1.31k
                        o->write_characters("\": ", 3);
9801
1.31k
                        dump(i->second, true, ensure_ascii, indent_step, new_indent);
9802
1.31k
                        o->write_characters(",\n", 2);
9803
1.31k
                    }
9804
360
9805
360
                    // last element
9806
360
                    assert(i != val.m_value.object->cend());
9807
360
                    assert(std::next(i) == val.m_value.object->cend());
9808
360
                    o->write_characters(indent_string.c_str(), new_indent);
9809
360
                    o->write_character('\"');
9810
360
                    dump_escaped(i->first, ensure_ascii);
9811
360
                    o->write_characters("\": ", 3);
9812
360
                    dump(i->second, true, ensure_ascii, indent_step, new_indent);
9813
360
9814
360
                    o->write_character('\n');
9815
360
                    o->write_characters(indent_string.c_str(), current_indent);
9816
360
                    o->write_character('}');
9817
360
                }
9818
597
                else
9819
597
                {
9820
237
                    o->write_character('{');
9821
237
9822
237
                    // first n-1 elements
9823
237
                    auto i = val.m_value.object->cbegin();
9824
801
                    for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
9825
564
                    {
9826
564
                        o->write_character('\"');
9827
564
                        dump_escaped(i->first, ensure_ascii);
9828
564
                        o->write_characters("\":", 2);
9829
564
                        dump(i->second, false, ensure_ascii, indent_step, current_indent);
9830
564
                        o->write_character(',');
9831
564
                    }
9832
237
9833
237
                    // last element
9834
237
                    assert(i != val.m_value.object->cend());
9835
237
                    assert(std::next(i) == val.m_value.object->cend());
9836
237
                    o->write_character('\"');
9837
237
                    dump_escaped(i->first, ensure_ascii);
9838
237
                    o->write_characters("\":", 2);
9839
237
                    dump(i->second, false, ensure_ascii, indent_step, current_indent);
9840
237
9841
237
                    o->write_character('}');
9842
237
                }
9843
597
9844
597
                return;
9845
597
            }
9846
597
9847
597
            case value_t::array:
9848
1
            {
9849
1
                if (val.m_value.array->empty())
9850
1
                {
9851
0
                    o->write_characters("[]", 2);
9852
0
                    return;
9853
0
                }
9854
1
9855
1
                if (pretty_print)
9856
1
                {
9857
1
                    o->write_characters("[\n", 2);
9858
1
9859
1
                    // variable to hold indentation for recursive calls
9860
1
                    const auto new_indent = current_indent + indent_step;
9861
1
                    if (JSON_UNLIKELY(indent_string.size() < new_indent))
9862
1
                    {
9863
0
                        indent_string.resize(indent_string.size() * 2, ' ');
9864
0
                    }
9865
1
9866
1
                    // first n-1 elements
9867
1
                    for (auto i = val.m_value.array->cbegin();
9868
1
                            i != val.m_value.array->cend() - 1; ++i)
9869
1
                    {
9870
0
                        o->write_characters(indent_string.c_str(), new_indent);
9871
0
                        dump(*i, true, ensure_ascii, indent_step, new_indent);
9872
0
                        o->write_characters(",\n", 2);
9873
0
                    }
9874
1
9875
1
                    // last element
9876
1
                    assert(not val.m_value.array->empty());
9877
1
                    o->write_characters(indent_string.c_str(), new_indent);
9878
1
                    dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
9879
1
9880
1
                    o->write_character('\n');
9881
1
                    o->write_characters(indent_string.c_str(), current_indent);
9882
1
                    o->write_character(']');
9883
1
                }
9884
1
                else
9885
1
                {
9886
0
                    o->write_character('[');
9887
0
9888
0
                    // first n-1 elements
9889
0
                    for (auto i = val.m_value.array->cbegin();
9890
0
                            i != val.m_value.array->cend() - 1; ++i)
9891
0
                    {
9892
0
                        dump(*i, false, ensure_ascii, indent_step, current_indent);
9893
0
                        o->write_character(',');
9894
0
                    }
9895
0
9896
0
                    // last element
9897
0
                    assert(not val.m_value.array->empty());
9898
0
                    dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
9899
0
9900
0
                    o->write_character(']');
9901
0
                }
9902
1
9903
1
                return;
9904
1
            }
9905
1
9906
1.67k
            case value_t::string:
9907
1.67k
            {
9908
1.67k
                o->write_character('\"');
9909
1.67k
                dump_escaped(*val.m_value.string, ensure_ascii);
9910
1.67k
                o->write_character('\"');
9911
1.67k
                return;
9912
1
            }
9913
1
9914
2
            case value_t::boolean:
9915
2
            {
9916
2
                if (val.m_value.boolean)
9917
2
                {
9918
2
                    o->write_characters("true", 4);
9919
2
                }
9920
2
                else
9921
2
                {
9922
0
                    o->write_characters("false", 5);
9923
0
                }
9924
2
                return;
9925
1
            }
9926
1
9927
2
            case value_t::number_integer:
9928
2
            {
9929
2
                dump_integer(val.m_value.number_integer);
9930
2
                return;
9931
1
            }
9932
1
9933
293
            case value_t::number_unsigned:
9934
293
            {
9935
293
                dump_integer(val.m_value.number_unsigned);
9936
293
                return;
9937
1
            }
9938
1
9939
7
            case value_t::number_float:
9940
7
            {
9941
7
                dump_float(val.m_value.number_float);
9942
7
                return;
9943
1
            }
9944
1
9945
1
            case value_t::discarded:
9946
0
            {
9947
0
                o->write_characters("<discarded>", 11);
9948
0
                return;
9949
1
            }
9950
1
9951
14
            case value_t::null:
9952
14
            {
9953
14
                o->write_characters("null", 4);
9954
14
                return;
9955
1
            }
9956
0
        }
9957
2.59k
    }
9958
9959
  private:
9960
    /*!
9961
    @brief dump escaped string
9962
9963
    Escape a string by replacing certain special characters by a sequence of an
9964
    escape character (backslash) and another character and other control
9965
    characters by a sequence of "\u" followed by a four-digit hex
9966
    representation. The escaped string is written to output stream @a o.
9967
9968
    @param[in] s  the string to escape
9969
    @param[in] ensure_ascii  whether to escape non-ASCII characters with
9970
                             \uXXXX sequences
9971
9972
    @complexity Linear in the length of string @a s.
9973
    */
9974
    void dump_escaped(const string_t& s, const bool ensure_ascii)
9975
4.14k
    {
9976
4.14k
        uint32_t codepoint;
9977
4.14k
        uint8_t state = UTF8_ACCEPT;
9978
4.14k
        std::size_t bytes = 0;  // number of bytes written to string_buffer
9979
4.14k
9980
27.6k
        for (std::size_t i = 0; i < s.size(); ++i)
9981
23.5k
        {
9982
23.5k
            const auto byte = static_cast<uint8_t>(s[i]);
9983
23.5k
9984
23.5k
            switch (decode(state, codepoint, byte))
9985
23.5k
            {
9986
23.5k
                case UTF8_ACCEPT:  // decode found a new code point
9987
23.5k
                {
9988
23.5k
                    switch (codepoint)
9989
23.5k
                    {
9990
23.5k
                        case 0x08: // backspace
9991
0
                        {
9992
0
                            string_buffer[bytes++] = '\\';
9993
0
                            string_buffer[bytes++] = 'b';
9994
0
                            break;
9995
0
                        }
9996
0
9997
0
                        case 0x09: // horizontal tab
9998
0
                        {
9999
0
                            string_buffer[bytes++] = '\\';
10000
0
                            string_buffer[bytes++] = 't';
10001
0
                            break;
10002
0
                        }
10003
0
10004
0
                        case 0x0A: // newline
10005
0
                        {
10006
0
                            string_buffer[bytes++] = '\\';
10007
0
                            string_buffer[bytes++] = 'n';
10008
0
                            break;
10009
0
                        }
10010
0
10011
0
                        case 0x0C: // formfeed
10012
0
                        {
10013
0
                            string_buffer[bytes++] = '\\';
10014
0
                            string_buffer[bytes++] = 'f';
10015
0
                            break;
10016
0
                        }
10017
0
10018
0
                        case 0x0D: // carriage return
10019
0
                        {
10020
0
                            string_buffer[bytes++] = '\\';
10021
0
                            string_buffer[bytes++] = 'r';
10022
0
                            break;
10023
0
                        }
10024
0
10025
0
                        case 0x22: // quotation mark
10026
0
                        {
10027
0
                            string_buffer[bytes++] = '\\';
10028
0
                            string_buffer[bytes++] = '\"';
10029
0
                            break;
10030
0
                        }
10031
0
10032
0
                        case 0x5C: // reverse solidus
10033
0
                        {
10034
0
                            string_buffer[bytes++] = '\\';
10035
0
                            string_buffer[bytes++] = '\\';
10036
0
                            break;
10037
0
                        }
10038
0
10039
23.5k
                        default:
10040
23.5k
                        {
10041
23.5k
                            // escape control characters (0x00..0x1F) or, if
10042
23.5k
                            // ensure_ascii parameter is used, non-ASCII characters
10043
23.5k
                            if ((codepoint <= 0x1F) or (ensure_ascii and (codepoint >= 0x7F)))
10044
23.5k
                            {
10045
0
                                if (codepoint <= 0xFFFF)
10046
0
                                {
10047
0
                                    std::snprintf(string_buffer.data() + bytes, 7, "\\u%04x",
10048
0
                                                  static_cast<uint16_t>(codepoint));
10049
0
                                    bytes += 6;
10050
0
                                }
10051
0
                                else
10052
0
                                {
10053
0
                                    std::snprintf(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
10054
0
                                                  static_cast<uint16_t>(0xD7C0 + (codepoint >> 10)),
10055
0
                                                  static_cast<uint16_t>(0xDC00 + (codepoint & 0x3FF)));
10056
0
                                    bytes += 12;
10057
0
                                }
10058
0
                            }
10059
23.5k
                            else
10060
23.5k
                            {
10061
23.5k
                                // copy byte to buffer (all previous bytes
10062
23.5k
                                // been copied have in default case above)
10063
23.5k
                                string_buffer[bytes++] = s[i];
10064
23.5k
                            }
10065
23.5k
                            break;
10066
0
                        }
10067
23.5k
                    }
10068
23.5k
10069
23.5k
                    // write buffer and reset index; there must be 13 bytes
10070
23.5k
                    // left, as this is the maximal number of bytes to be
10071
23.5k
                    // written ("\uxxxx\uxxxx\0") for one code point
10072
23.5k
                    if (string_buffer.size() - bytes < 13)
10073
23.5k
                    {
10074
0
                        o->write_characters(string_buffer.data(), bytes);
10075
0
                        bytes = 0;
10076
0
                    }
10077
23.5k
                    break;
10078
23.5k
                }
10079
23.5k
10080
23.5k
                case UTF8_REJECT:  // decode found invalid UTF-8 byte
10081
0
                {
10082
0
                    std::string sn(3, '\0');
10083
0
                    snprintf(&sn[0], sn.size(), "%.2X", byte);
10084
0
                    JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + sn));
10085
23.5k
                }
10086
23.5k
10087
23.5k
                default:  // decode found yet incomplete multi-byte code point
10088
0
                {
10089
0
                    if (not ensure_ascii)
10090
0
                    {
10091
0
                        // code point will not be escaped - copy byte to buffer
10092
0
                        string_buffer[bytes++] = s[i];
10093
0
                    }
10094
0
                    break;
10095
23.5k
                }
10096
23.5k
            }
10097
23.5k
        }
10098
4.14k
10099
4.14k
        if (JSON_LIKELY(state == UTF8_ACCEPT))
10100
4.14k
        {
10101
4.14k
            // write buffer
10102
4.14k
            if (bytes > 0)
10103
4.14k
            {
10104
4.14k
                o->write_characters(string_buffer.data(), bytes);
10105
4.14k
            }
10106
4.14k
        }
10107
4.14k
        else
10108
4.14k
        {
10109
0
            // we finish reading, but do not accept: string was incomplete
10110
0
            std::string sn(3, '\0');
10111
0
            snprintf(&sn[0], sn.size(), "%.2X", static_cast<uint8_t>(s.back()));
10112
0
            JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + sn));
10113
0
        }
10114
4.14k
    }
10115
10116
    /*!
10117
    @brief dump an integer
10118
10119
    Dump a given integer to output stream @a o. Works internally with
10120
    @a number_buffer.
10121
10122
    @param[in] x  integer number (signed or unsigned) to dump
10123
    @tparam NumberType either @a number_integer_t or @a number_unsigned_t
10124
    */
10125
    template<typename NumberType, detail::enable_if_t<
10126
                 std::is_same<NumberType, number_unsigned_t>::value or
10127
                 std::is_same<NumberType, number_integer_t>::value,
10128
                 int> = 0>
10129
    void dump_integer(NumberType x)
10130
295
    {
10131
295
        // special case for "0"
10132
295
        if (x == 0)
10133
295
        {
10134
11
            o->write_character('0');
10135
11
            return;
10136
11
        }
10137
295
10138
295
        const bool is_negative = (x <= 0) and (x != 0);  // see issue #755
10139
284
        std::size_t i = 0;
10140
284
10141
797
        while (x != 0)
10142
513
        {
10143
513
            // spare 1 byte for '\0'
10144
513
            assert(i < number_buffer.size() - 1);
10145
513
10146
513
            const auto digit = std::labs(static_cast<long>(x % 10));
10147
513
            number_buffer[i++] = static_cast<char>('0' + digit);
10148
513
            x /= 10;
10149
513
        }
10150
284
10151
284
        if (is_negative)
10152
284
        {
10153
1
            // make sure there is capacity for the '-'
10154
1
            assert(i < number_buffer.size() - 2);
10155
1
            number_buffer[i++] = '-';
10156
1
        }
10157
284
10158
284
        std::reverse(number_buffer.begin(), number_buffer.begin() + i);
10159
284
        o->write_characters(number_buffer.data(), i);
10160
284
    }
_ZN8nlohmann6detail10serializerINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEE12dump_integerIlLi0EEEvT_
Line
Count
Source
10130
2
    {
10131
2
        // special case for "0"
10132
2
        if (x == 0)
10133
2
        {
10134
0
            o->write_character('0');
10135
0
            return;
10136
0
        }
10137
2
10138
2
        const bool is_negative = (x <= 0) and (x != 0);  // see issue #755
10139
2
        std::size_t i = 0;
10140
2
10141
9
        while (x != 0)
10142
7
        {
10143
7
            // spare 1 byte for '\0'
10144
7
            assert(i < number_buffer.size() - 1);
10145
7
10146
7
            const auto digit = std::labs(static_cast<long>(x % 10));
10147
7
            number_buffer[i++] = static_cast<char>('0' + digit);
10148
7
            x /= 10;
10149
7
        }
10150
2
10151
2
        if (is_negative)
10152
2
        {
10153
1
            // make sure there is capacity for the '-'
10154
1
            assert(i < number_buffer.size() - 2);
10155
1
            number_buffer[i++] = '-';
10156
1
        }
10157
2
10158
2
        std::reverse(number_buffer.begin(), number_buffer.begin() + i);
10159
2
        o->write_characters(number_buffer.data(), i);
10160
2
    }
_ZN8nlohmann6detail10serializerINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEE12dump_integerImLi0EEEvT_
Line
Count
Source
10130
293
    {
10131
293
        // special case for "0"
10132
293
        if (x == 0)
10133
293
        {
10134
11
            o->write_character('0');
10135
11
            return;
10136
11
        }
10137
293
10138
293
        const bool is_negative = (x <= 0) and (x != 0);  // see issue #755
10139
282
        std::size_t i = 0;
10140
282
10141
788
        while (x != 0)
10142
506
        {
10143
506
            // spare 1 byte for '\0'
10144
506
            assert(i < number_buffer.size() - 1);
10145
506
10146
506
            const auto digit = std::labs(static_cast<long>(x % 10));
10147
506
            number_buffer[i++] = static_cast<char>('0' + digit);
10148
506
            x /= 10;
10149
506
        }
10150
282
10151
282
        if (is_negative)
10152
282
        {
10153
0
            // make sure there is capacity for the '-'
10154
0
            assert(i < number_buffer.size() - 2);
10155
0
            number_buffer[i++] = '-';
10156
0
        }
10157
282
10158
282
        std::reverse(number_buffer.begin(), number_buffer.begin() + i);
10159
282
        o->write_characters(number_buffer.data(), i);
10160
282
    }
10161
10162
    /*!
10163
    @brief dump a floating-point number
10164
10165
    Dump a given floating-point number to output stream @a o. Works internally
10166
    with @a number_buffer.
10167
10168
    @param[in] x  floating-point number to dump
10169
    */
10170
    void dump_float(number_float_t x)
10171
7
    {
10172
7
        // NaN / inf
10173
7
        if (not std::isfinite(x))
10174
7
        {
10175
0
            o->write_characters("null", 4);
10176
0
            return;
10177
0
        }
10178
7
10179
7
        // If number_float_t is an IEEE-754 single or double precision number,
10180
7
        // use the Grisu2 algorithm to produce short numbers which are
10181
7
        // guaranteed to round-trip, using strtof and strtod, resp.
10182
7
        //
10183
7
        // NB: The test below works if <long double> == <double>.
10184
7
        static constexpr bool is_ieee_single_or_double
10185
7
            = (std::numeric_limits<number_float_t>::is_iec559 and std::numeric_limits<number_float_t>::digits == 24 and std::numeric_limits<number_float_t>::max_exponent == 128) or
10186
7
              (std::numeric_limits<number_float_t>::is_iec559 and std::numeric_limits<number_float_t>::digits == 53 and std::numeric_limits<number_float_t>::max_exponent == 1024);
10187
7
10188
7
        dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
10189
7
    }
10190
10191
    void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
10192
7
    {
10193
7
        char* begin = number_buffer.data();
10194
7
        char* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
10195
7
10196
7
        o->write_characters(begin, static_cast<size_t>(end - begin));
10197
7
    }
10198
10199
    void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
10200
    {
10201
        // get number of digits for a float -> text -> float round-trip
10202
        static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
10203
10204
        // the actual conversion
10205
        std::ptrdiff_t len = snprintf(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
10206
10207
        // negative value indicates an error
10208
        assert(len > 0);
10209
        // check if buffer was large enough
10210
        assert(static_cast<std::size_t>(len) < number_buffer.size());
10211
10212
        // erase thousands separator
10213
        if (thousands_sep != '\0')
10214
        {
10215
            const auto end = std::remove(number_buffer.begin(),
10216
                                         number_buffer.begin() + len, thousands_sep);
10217
            std::fill(end, number_buffer.end(), '\0');
10218
            assert((end - number_buffer.begin()) <= len);
10219
            len = (end - number_buffer.begin());
10220
        }
10221
10222
        // convert decimal point to '.'
10223
        if (decimal_point != '\0' and decimal_point != '.')
10224
        {
10225
            const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
10226
            if (dec_pos != number_buffer.end())
10227
            {
10228
                *dec_pos = '.';
10229
            }
10230
        }
10231
10232
        o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
10233
10234
        // determine if need to append ".0"
10235
        const bool value_is_int_like =
10236
            std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
10237
                         [](char c)
10238
        {
10239
            return (c == '.' or c == 'e');
10240
        });
10241
10242
        if (value_is_int_like)
10243
        {
10244
            o->write_characters(".0", 2);
10245
        }
10246
    }
10247
10248
    /*!
10249
    @brief check whether a string is UTF-8 encoded
10250
10251
    The function checks each byte of a string whether it is UTF-8 encoded. The
10252
    result of the check is stored in the @a state parameter. The function must
10253
    be called initially with state 0 (accept). State 1 means the string must
10254
    be rejected, because the current byte is not allowed. If the string is
10255
    completely processed, but the state is non-zero, the string ended
10256
    prematurely; that is, the last byte indicated more bytes should have
10257
    followed.
10258
10259
    @param[in,out] state  the state of the decoding
10260
    @param[in,out] codep  codepoint (valid only if resulting state is UTF8_ACCEPT)
10261
    @param[in] byte       next byte to decode
10262
    @return               new state
10263
10264
    @note The function has been edited: a std::array is used.
10265
10266
    @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
10267
    @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
10268
    */
10269
    static uint8_t decode(uint8_t& state, uint32_t& codep, const uint8_t byte) noexcept
10270
23.5k
    {
10271
23.5k
        static const std::array<uint8_t, 400> utf8d =
10272
23.5k
        {
10273
23.5k
            {
10274
23.5k
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F
10275
23.5k
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F
10276
23.5k
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F
10277
23.5k
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F
10278
23.5k
                1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F
10279
23.5k
                7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF
10280
23.5k
                8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF
10281
23.5k
                0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
10282
23.5k
                0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
10283
23.5k
                0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
10284
23.5k
                1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2
10285
23.5k
                1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4
10286
23.5k
                1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6
10287
23.5k
                1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8
10288
23.5k
            }
10289
23.5k
        };
10290
23.5k
10291
23.5k
        const uint8_t type = utf8d[byte];
10292
23.5k
10293
23.5k
        codep = (state != UTF8_ACCEPT)
10294
23.5k
                ? (byte & 0x3fu) | (codep << 6)
10295
23.5k
                : static_cast<uint32_t>(0xff >> type) & (byte);
10296
23.5k
10297
23.5k
        state = utf8d[256u + state * 16u + type];
10298
23.5k
        return state;
10299
23.5k
    }
10300
10301
  private:
10302
    /// the output of the serializer
10303
    output_adapter_t<char> o = nullptr;
10304
10305
    /// a (hopefully) large enough character buffer
10306
    std::array<char, 64> number_buffer{{}};
10307
10308
    /// the locale
10309
    const std::lconv* loc = nullptr;
10310
    /// the locale's thousand separator character
10311
    const char thousands_sep = '\0';
10312
    /// the locale's decimal point character
10313
    const char decimal_point = '\0';
10314
10315
    /// string buffer
10316
    std::array<char, 512> string_buffer{{}};
10317
10318
    /// the indentation character
10319
    const char indent_char;
10320
    /// the indentation string
10321
    string_t indent_string;
10322
};
10323
}
10324
}
10325
10326
// #include <nlohmann/detail/json_ref.hpp>
10327
10328
10329
#include <initializer_list>
10330
#include <utility>
10331
10332
namespace nlohmann
10333
{
10334
namespace detail
10335
{
10336
template<typename BasicJsonType>
10337
class json_ref
10338
{
10339
  public:
10340
    using value_type = BasicJsonType;
10341
10342
    json_ref(value_type&& value)
10343
        : owned_value(std::move(value)), value_ref(&owned_value), is_rvalue(true)
10344
    {}
10345
10346
    json_ref(const value_type& value)
10347
        : value_ref(const_cast<value_type*>(&value)), is_rvalue(false)
10348
    {}
10349
10350
    json_ref(std::initializer_list<json_ref> init)
10351
        : owned_value(init), value_ref(&owned_value), is_rvalue(true)
10352
    {}
10353
10354
    template<class... Args>
10355
    json_ref(Args&& ... args)
10356
        : owned_value(std::forward<Args>(args)...), value_ref(&owned_value), is_rvalue(true)
10357
    {}
10358
10359
    // class should be movable only
10360
    json_ref(json_ref&&) = default;
10361
    json_ref(const json_ref&) = delete;
10362
    json_ref& operator=(const json_ref&) = delete;
10363
10364
    value_type moved_or_copied() const
10365
    {
10366
        if (is_rvalue)
10367
        {
10368
            return std::move(*value_ref);
10369
        }
10370
        return *value_ref;
10371
    }
10372
10373
    value_type const& operator*() const
10374
    {
10375
        return *static_cast<value_type const*>(value_ref);
10376
    }
10377
10378
    value_type const* operator->() const
10379
    {
10380
        return static_cast<value_type const*>(value_ref);
10381
    }
10382
10383
  private:
10384
    mutable value_type owned_value = nullptr;
10385
    value_type* value_ref = nullptr;
10386
    const bool is_rvalue;
10387
};
10388
}
10389
}
10390
10391
// #include <nlohmann/detail/json_pointer.hpp>
10392
10393
10394
#include <cassert> // assert
10395
#include <numeric> // accumulate
10396
#include <string> // string
10397
#include <vector> // vector
10398
10399
// #include <nlohmann/detail/macro_scope.hpp>
10400
10401
// #include <nlohmann/detail/exceptions.hpp>
10402
10403
// #include <nlohmann/detail/value_t.hpp>
10404
10405
10406
namespace nlohmann
10407
{
10408
template<typename BasicJsonType>
10409
class json_pointer
10410
{
10411
    // allow basic_json to access private members
10412
    NLOHMANN_BASIC_JSON_TPL_DECLARATION
10413
    friend class basic_json;
10414
10415
  public:
10416
    /*!
10417
    @brief create JSON pointer
10418
10419
    Create a JSON pointer according to the syntax described in
10420
    [Section 3 of RFC6901](https://tools.ietf.org/html/rfc6901#section-3).
10421
10422
    @param[in] s  string representing the JSON pointer; if omitted, the empty
10423
                  string is assumed which references the whole JSON value
10424
10425
    @throw parse_error.107 if the given JSON pointer @a s is nonempty and does
10426
                           not begin with a slash (`/`); see example below
10427
10428
    @throw parse_error.108 if a tilde (`~`) in the given JSON pointer @a s is
10429
    not followed by `0` (representing `~`) or `1` (representing `/`); see
10430
    example below
10431
10432
    @liveexample{The example shows the construction several valid JSON pointers
10433
    as well as the exceptional behavior.,json_pointer}
10434
10435
    @since version 2.0.0
10436
    */
10437
    explicit json_pointer(const std::string& s = "")
10438
        : reference_tokens(split(s))
10439
    {}
10440
10441
    /*!
10442
    @brief return a string representation of the JSON pointer
10443
10444
    @invariant For each JSON pointer `ptr`, it holds:
10445
    @code {.cpp}
10446
    ptr == json_pointer(ptr.to_string());
10447
    @endcode
10448
10449
    @return a string representation of the JSON pointer
10450
10451
    @liveexample{The example shows the result of `to_string`.,
10452
    json_pointer__to_string}
10453
10454
    @since version 2.0.0
10455
    */
10456
    std::string to_string() const noexcept
10457
    {
10458
        return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
10459
                               std::string{},
10460
                               [](const std::string & a, const std::string & b)
10461
        {
10462
            return a + "/" + escape(b);
10463
        });
10464
    }
10465
10466
    /// @copydoc to_string()
10467
    operator std::string() const
10468
    {
10469
        return to_string();
10470
    }
10471
10472
    /*!
10473
    @param[in] s  reference token to be converted into an array index
10474
10475
    @return integer representation of @a s
10476
10477
    @throw out_of_range.404 if string @a s could not be converted to an integer
10478
    */
10479
    static int array_index(const std::string& s)
10480
    {
10481
        std::size_t processed_chars = 0;
10482
        const int res = std::stoi(s, &processed_chars);
10483
10484
        // check if the string was completely read
10485
        if (JSON_UNLIKELY(processed_chars != s.size()))
10486
        {
10487
            JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'"));
10488
        }
10489
10490
        return res;
10491
    }
10492
10493
  private:
10494
    /*!
10495
    @brief remove and return last reference pointer
10496
    @throw out_of_range.405 if JSON pointer has no parent
10497
    */
10498
    std::string pop_back()
10499
    {
10500
        if (JSON_UNLIKELY(is_root()))
10501
        {
10502
            JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
10503
        }
10504
10505
        auto last = reference_tokens.back();
10506
        reference_tokens.pop_back();
10507
        return last;
10508
    }
10509
10510
    /// return whether pointer points to the root document
10511
    bool is_root() const
10512
    {
10513
        return reference_tokens.empty();
10514
    }
10515
10516
    json_pointer top() const
10517
    {
10518
        if (JSON_UNLIKELY(is_root()))
10519
        {
10520
            JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
10521
        }
10522
10523
        json_pointer result = *this;
10524
        result.reference_tokens = {reference_tokens[0]};
10525
        return result;
10526
    }
10527
10528
    /*!
10529
    @brief create and return a reference to the pointed to value
10530
10531
    @complexity Linear in the number of reference tokens.
10532
10533
    @throw parse_error.109 if array index is not a number
10534
    @throw type_error.313 if value cannot be unflattened
10535
    */
10536
    BasicJsonType& get_and_create(BasicJsonType& j) const
10537
    {
10538
        using size_type = typename BasicJsonType::size_type;
10539
        auto result = &j;
10540
10541
        // in case no reference tokens exist, return a reference to the JSON value
10542
        // j which will be overwritten by a primitive value
10543
        for (const auto& reference_token : reference_tokens)
10544
        {
10545
            switch (result->m_type)
10546
            {
10547
                case detail::value_t::null:
10548
                {
10549
                    if (reference_token == "0")
10550
                    {
10551
                        // start a new array if reference token is 0
10552
                        result = &result->operator[](0);
10553
                    }
10554
                    else
10555
                    {
10556
                        // start a new object otherwise
10557
                        result = &result->operator[](reference_token);
10558
                    }
10559
                    break;
10560
                }
10561
10562
                case detail::value_t::object:
10563
                {
10564
                    // create an entry in the object
10565
                    result = &result->operator[](reference_token);
10566
                    break;
10567
                }
10568
10569
                case detail::value_t::array:
10570
                {
10571
                    // create an entry in the array
10572
                    JSON_TRY
10573
                    {
10574
                        result = &result->operator[](static_cast<size_type>(array_index(reference_token)));
10575
                    }
10576
                    JSON_CATCH(std::invalid_argument&)
10577
                    {
10578
                        JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
10579
                    }
10580
                    break;
10581
                }
10582
10583
                /*
10584
                The following code is only reached if there exists a reference
10585
                token _and_ the current value is primitive. In this case, we have
10586
                an error situation, because primitive values may only occur as
10587
                single value; that is, with an empty list of reference tokens.
10588
                */
10589
                default:
10590
                    JSON_THROW(detail::type_error::create(313, "invalid value to unflatten"));
10591
            }
10592
        }
10593
10594
        return *result;
10595
    }
10596
10597
    /*!
10598
    @brief return a reference to the pointed to value
10599
10600
    @note This version does not throw if a value is not present, but tries to
10601
          create nested values instead. For instance, calling this function
10602
          with pointer `"/this/that"` on a null value is equivalent to calling
10603
          `operator[]("this").operator[]("that")` on that value, effectively
10604
          changing the null value to an object.
10605
10606
    @param[in] ptr  a JSON value
10607
10608
    @return reference to the JSON value pointed to by the JSON pointer
10609
10610
    @complexity Linear in the length of the JSON pointer.
10611
10612
    @throw parse_error.106   if an array index begins with '0'
10613
    @throw parse_error.109   if an array index was not a number
10614
    @throw out_of_range.404  if the JSON pointer can not be resolved
10615
    */
10616
    BasicJsonType& get_unchecked(BasicJsonType* ptr) const
10617
    {
10618
        using size_type = typename BasicJsonType::size_type;
10619
        for (const auto& reference_token : reference_tokens)
10620
        {
10621
            // convert null values to arrays or objects before continuing
10622
            if (ptr->m_type == detail::value_t::null)
10623
            {
10624
                // check if reference token is a number
10625
                const bool nums =
10626
                    std::all_of(reference_token.begin(), reference_token.end(),
10627
                                [](const char x)
10628
                {
10629
                    return (x >= '0' and x <= '9');
10630
                });
10631
10632
                // change value to array for numbers or "-" or to object otherwise
10633
                *ptr = (nums or reference_token == "-")
10634
                       ? detail::value_t::array
10635
                       : detail::value_t::object;
10636
            }
10637
10638
            switch (ptr->m_type)
10639
            {
10640
                case detail::value_t::object:
10641
                {
10642
                    // use unchecked object access
10643
                    ptr = &ptr->operator[](reference_token);
10644
                    break;
10645
                }
10646
10647
                case detail::value_t::array:
10648
                {
10649
                    // error condition (cf. RFC 6901, Sect. 4)
10650
                    if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
10651
                    {
10652
                        JSON_THROW(detail::parse_error::create(106, 0,
10653
                                                               "array index '" + reference_token +
10654
                                                               "' must not begin with '0'"));
10655
                    }
10656
10657
                    if (reference_token == "-")
10658
                    {
10659
                        // explicitly treat "-" as index beyond the end
10660
                        ptr = &ptr->operator[](ptr->m_value.array->size());
10661
                    }
10662
                    else
10663
                    {
10664
                        // convert array index to number; unchecked access
10665
                        JSON_TRY
10666
                        {
10667
                            ptr = &ptr->operator[](
10668
                                static_cast<size_type>(array_index(reference_token)));
10669
                        }
10670
                        JSON_CATCH(std::invalid_argument&)
10671
                        {
10672
                            JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
10673
                        }
10674
                    }
10675
                    break;
10676
                }
10677
10678
                default:
10679
                    JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
10680
            }
10681
        }
10682
10683
        return *ptr;
10684
    }
10685
10686
    /*!
10687
    @throw parse_error.106   if an array index begins with '0'
10688
    @throw parse_error.109   if an array index was not a number
10689
    @throw out_of_range.402  if the array index '-' is used
10690
    @throw out_of_range.404  if the JSON pointer can not be resolved
10691
    */
10692
    BasicJsonType& get_checked(BasicJsonType* ptr) const
10693
    {
10694
        using size_type = typename BasicJsonType::size_type;
10695
        for (const auto& reference_token : reference_tokens)
10696
        {
10697
            switch (ptr->m_type)
10698
            {
10699
                case detail::value_t::object:
10700
                {
10701
                    // note: at performs range check
10702
                    ptr = &ptr->at(reference_token);
10703
                    break;
10704
                }
10705
10706
                case detail::value_t::array:
10707
                {
10708
                    if (JSON_UNLIKELY(reference_token == "-"))
10709
                    {
10710
                        // "-" always fails the range check
10711
                        JSON_THROW(detail::out_of_range::create(402,
10712
                                                                "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
10713
                                                                ") is out of range"));
10714
                    }
10715
10716
                    // error condition (cf. RFC 6901, Sect. 4)
10717
                    if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
10718
                    {
10719
                        JSON_THROW(detail::parse_error::create(106, 0,
10720
                                                               "array index '" + reference_token +
10721
                                                               "' must not begin with '0'"));
10722
                    }
10723
10724
                    // note: at performs range check
10725
                    JSON_TRY
10726
                    {
10727
                        ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
10728
                    }
10729
                    JSON_CATCH(std::invalid_argument&)
10730
                    {
10731
                        JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
10732
                    }
10733
                    break;
10734
                }
10735
10736
                default:
10737
                    JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
10738
            }
10739
        }
10740
10741
        return *ptr;
10742
    }
10743
10744
    /*!
10745
    @brief return a const reference to the pointed to value
10746
10747
    @param[in] ptr  a JSON value
10748
10749
    @return const reference to the JSON value pointed to by the JSON
10750
    pointer
10751
10752
    @throw parse_error.106   if an array index begins with '0'
10753
    @throw parse_error.109   if an array index was not a number
10754
    @throw out_of_range.402  if the array index '-' is used
10755
    @throw out_of_range.404  if the JSON pointer can not be resolved
10756
    */
10757
    const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
10758
    {
10759
        using size_type = typename BasicJsonType::size_type;
10760
        for (const auto& reference_token : reference_tokens)
10761
        {
10762
            switch (ptr->m_type)
10763
            {
10764
                case detail::value_t::object:
10765
                {
10766
                    // use unchecked object access
10767
                    ptr = &ptr->operator[](reference_token);
10768
                    break;
10769
                }
10770
10771
                case detail::value_t::array:
10772
                {
10773
                    if (JSON_UNLIKELY(reference_token == "-"))
10774
                    {
10775
                        // "-" cannot be used for const access
10776
                        JSON_THROW(detail::out_of_range::create(402,
10777
                                                                "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
10778
                                                                ") is out of range"));
10779
                    }
10780
10781
                    // error condition (cf. RFC 6901, Sect. 4)
10782
                    if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
10783
                    {
10784
                        JSON_THROW(detail::parse_error::create(106, 0,
10785
                                                               "array index '" + reference_token +
10786
                                                               "' must not begin with '0'"));
10787
                    }
10788
10789
                    // use unchecked array access
10790
                    JSON_TRY
10791
                    {
10792
                        ptr = &ptr->operator[](
10793
                            static_cast<size_type>(array_index(reference_token)));
10794
                    }
10795
                    JSON_CATCH(std::invalid_argument&)
10796
                    {
10797
                        JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
10798
                    }
10799
                    break;
10800
                }
10801
10802
                default:
10803
                    JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
10804
            }
10805
        }
10806
10807
        return *ptr;
10808
    }
10809
10810
    /*!
10811
    @throw parse_error.106   if an array index begins with '0'
10812
    @throw parse_error.109   if an array index was not a number
10813
    @throw out_of_range.402  if the array index '-' is used
10814
    @throw out_of_range.404  if the JSON pointer can not be resolved
10815
    */
10816
    const BasicJsonType& get_checked(const BasicJsonType* ptr) const
10817
    {
10818
        using size_type = typename BasicJsonType::size_type;
10819
        for (const auto& reference_token : reference_tokens)
10820
        {
10821
            switch (ptr->m_type)
10822
            {
10823
                case detail::value_t::object:
10824
                {
10825
                    // note: at performs range check
10826
                    ptr = &ptr->at(reference_token);
10827
                    break;
10828
                }
10829
10830
                case detail::value_t::array:
10831
                {
10832
                    if (JSON_UNLIKELY(reference_token == "-"))
10833
                    {
10834
                        // "-" always fails the range check
10835
                        JSON_THROW(detail::out_of_range::create(402,
10836
                                                                "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
10837
                                                                ") is out of range"));
10838
                    }
10839
10840
                    // error condition (cf. RFC 6901, Sect. 4)
10841
                    if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
10842
                    {
10843
                        JSON_THROW(detail::parse_error::create(106, 0,
10844
                                                               "array index '" + reference_token +
10845
                                                               "' must not begin with '0'"));
10846
                    }
10847
10848
                    // note: at performs range check
10849
                    JSON_TRY
10850
                    {
10851
                        ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
10852
                    }
10853
                    JSON_CATCH(std::invalid_argument&)
10854
                    {
10855
                        JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
10856
                    }
10857
                    break;
10858
                }
10859
10860
                default:
10861
                    JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
10862
            }
10863
        }
10864
10865
        return *ptr;
10866
    }
10867
10868
    /*!
10869
    @brief split the string input to reference tokens
10870
10871
    @note This function is only called by the json_pointer constructor.
10872
          All exceptions below are documented there.
10873
10874
    @throw parse_error.107  if the pointer is not empty or begins with '/'
10875
    @throw parse_error.108  if character '~' is not followed by '0' or '1'
10876
    */
10877
    static std::vector<std::string> split(const std::string& reference_string)
10878
0
    {
10879
0
        std::vector<std::string> result;
10880
0
10881
0
        // special case: empty reference string -> no reference tokens
10882
0
        if (reference_string.empty())
10883
0
        {
10884
0
            return result;
10885
0
        }
10886
0
10887
0
        // check if nonempty reference string begins with slash
10888
0
        if (JSON_UNLIKELY(reference_string[0] != '/'))
10889
0
        {
10890
0
            JSON_THROW(detail::parse_error::create(107, 1,
10891
0
                                                   "JSON pointer must be empty or begin with '/' - was: '" +
10892
0
                                                   reference_string + "'"));
10893
0
        }
10894
0
10895
0
        // extract the reference tokens:
10896
0
        // - slash: position of the last read slash (or end of string)
10897
0
        // - start: position after the previous slash
10898
0
        for (
10899
0
            // search for the first slash after the first character
10900
0
            std::size_t slash = reference_string.find_first_of('/', 1),
10901
0
            // set the beginning of the first reference token
10902
0
            start = 1;
10903
0
            // we can stop if start == string::npos+1 = 0
10904
0
            start != 0;
10905
0
            // set the beginning of the next reference token
10906
0
            // (will eventually be 0 if slash == std::string::npos)
10907
0
            start = slash + 1,
10908
0
            // find next slash
10909
0
            slash = reference_string.find_first_of('/', start))
10910
0
        {
10911
0
            // use the text between the beginning of the reference token
10912
0
            // (start) and the last slash (slash).
10913
0
            auto reference_token = reference_string.substr(start, slash - start);
10914
0
10915
0
            // check reference tokens are properly escaped
10916
0
            for (std::size_t pos = reference_token.find_first_of('~');
10917
0
                    pos != std::string::npos;
10918
0
                    pos = reference_token.find_first_of('~', pos + 1))
10919
0
            {
10920
0
                assert(reference_token[pos] == '~');
10921
0
10922
0
                // ~ must be followed by 0 or 1
10923
0
                if (JSON_UNLIKELY(pos == reference_token.size() - 1 or
10924
0
                                  (reference_token[pos + 1] != '0' and
10925
0
                                   reference_token[pos + 1] != '1')))
10926
0
                {
10927
0
                    JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'"));
10928
0
                }
10929
0
            }
10930
0
10931
0
            // finally, store the reference token
10932
0
            unescape(reference_token);
10933
0
            result.push_back(reference_token);
10934
0
        }
10935
0
10936
0
        return result;
10937
0
    }
10938
10939
    /*!
10940
    @brief replace all occurrences of a substring by another string
10941
10942
    @param[in,out] s  the string to manipulate; changed so that all
10943
                   occurrences of @a f are replaced with @a t
10944
    @param[in]     f  the substring to replace with @a t
10945
    @param[in]     t  the string to replace @a f
10946
10947
    @pre The search string @a f must not be empty. **This precondition is
10948
    enforced with an assertion.**
10949
10950
    @since version 2.0.0
10951
    */
10952
    static void replace_substring(std::string& s, const std::string& f,
10953
                                  const std::string& t)
10954
0
    {
10955
0
        assert(not f.empty());
10956
0
        for (auto pos = s.find(f);                // find first occurrence of f
10957
0
                pos != std::string::npos;         // make sure f was found
10958
0
                s.replace(pos, f.size(), t),      // replace with t, and
10959
0
                pos = s.find(f, pos + t.size()))  // find next occurrence of f
10960
0
        {}
10961
0
    }
10962
10963
    /// escape "~"" to "~0" and "/" to "~1"
10964
    static std::string escape(std::string s)
10965
    {
10966
        replace_substring(s, "~", "~0");
10967
        replace_substring(s, "/", "~1");
10968
        return s;
10969
    }
10970
10971
    /// unescape "~1" to tilde and "~0" to slash (order is important!)
10972
    static void unescape(std::string& s)
10973
0
    {
10974
0
        replace_substring(s, "~1", "/");
10975
0
        replace_substring(s, "~0", "~");
10976
0
    }
10977
10978
    /*!
10979
    @param[in] reference_string  the reference string to the current value
10980
    @param[in] value             the value to consider
10981
    @param[in,out] result        the result object to insert values to
10982
10983
    @note Empty objects or arrays are flattened to `null`.
10984
    */
10985
    static void flatten(const std::string& reference_string,
10986
                        const BasicJsonType& value,
10987
                        BasicJsonType& result)
10988
    {
10989
        switch (value.m_type)
10990
        {
10991
            case detail::value_t::array:
10992
            {
10993
                if (value.m_value.array->empty())
10994
                {
10995
                    // flatten empty array as null
10996
                    result[reference_string] = nullptr;
10997
                }
10998
                else
10999
                {
11000
                    // iterate array and use index as reference string
11001
                    for (std::size_t i = 0; i < value.m_value.array->size(); ++i)
11002
                    {
11003
                        flatten(reference_string + "/" + std::to_string(i),
11004
                                value.m_value.array->operator[](i), result);
11005
                    }
11006
                }
11007
                break;
11008
            }
11009
11010
            case detail::value_t::object:
11011
            {
11012
                if (value.m_value.object->empty())
11013
                {
11014
                    // flatten empty object as null
11015
                    result[reference_string] = nullptr;
11016
                }
11017
                else
11018
                {
11019
                    // iterate object and use keys as reference string
11020
                    for (const auto& element : *value.m_value.object)
11021
                    {
11022
                        flatten(reference_string + "/" + escape(element.first), element.second, result);
11023
                    }
11024
                }
11025
                break;
11026
            }
11027
11028
            default:
11029
            {
11030
                // add primitive value with its reference string
11031
                result[reference_string] = value;
11032
                break;
11033
            }
11034
        }
11035
    }
11036
11037
    /*!
11038
    @param[in] value  flattened JSON
11039
11040
    @return unflattened JSON
11041
11042
    @throw parse_error.109 if array index is not a number
11043
    @throw type_error.314  if value is not an object
11044
    @throw type_error.315  if object values are not primitive
11045
    @throw type_error.313  if value cannot be unflattened
11046
    */
11047
    static BasicJsonType
11048
    unflatten(const BasicJsonType& value)
11049
    {
11050
        if (JSON_UNLIKELY(not value.is_object()))
11051
        {
11052
            JSON_THROW(detail::type_error::create(314, "only objects can be unflattened"));
11053
        }
11054
11055
        BasicJsonType result;
11056
11057
        // iterate the JSON object values
11058
        for (const auto& element : *value.m_value.object)
11059
        {
11060
            if (JSON_UNLIKELY(not element.second.is_primitive()))
11061
            {
11062
                JSON_THROW(detail::type_error::create(315, "values in object must be primitive"));
11063
            }
11064
11065
            // assign value to reference pointed to by JSON pointer; Note that if
11066
            // the JSON pointer is "" (i.e., points to the whole value), function
11067
            // get_and_create returns a reference to result itself. An assignment
11068
            // will then create a primitive value.
11069
            json_pointer(element.first).get_and_create(result) = element.second;
11070
        }
11071
11072
        return result;
11073
    }
11074
11075
    friend bool operator==(json_pointer const& lhs,
11076
                           json_pointer const& rhs) noexcept
11077
    {
11078
        return (lhs.reference_tokens == rhs.reference_tokens);
11079
    }
11080
11081
    friend bool operator!=(json_pointer const& lhs,
11082
                           json_pointer const& rhs) noexcept
11083
    {
11084
        return not (lhs == rhs);
11085
    }
11086
11087
    /// the reference tokens
11088
    std::vector<std::string> reference_tokens;
11089
};
11090
}
11091
11092
// #include <nlohmann/adl_serializer.hpp>
11093
11094
11095
#include <utility>
11096
11097
// #include <nlohmann/detail/conversions/from_json.hpp>
11098
11099
// #include <nlohmann/detail/conversions/to_json.hpp>
11100
11101
11102
namespace nlohmann
11103
{
11104
template<typename, typename>
11105
struct adl_serializer
11106
{
11107
    /*!
11108
    @brief convert a JSON value to any value type
11109
11110
    This function is usually called by the `get()` function of the
11111
    @ref basic_json class (either explicit or via conversion operators).
11112
11113
    @param[in] j         JSON value to read from
11114
    @param[in,out] val  value to write to
11115
    */
11116
    template<typename BasicJsonType, typename ValueType>
11117
    static auto from_json(BasicJsonType&& j, ValueType& val) noexcept(
11118
        noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val))) -> decltype(
11119
            ::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void()
11120
        )
11121
11.7k
    {
11122
11.7k
        ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
11123
11.7k
    }
_ZN8nlohmann14adl_serializerIbvE9from_jsonIRKNS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaS0_EEbEEDTcmclL_ZNS_12_GLOBAL__N_19from_jsonEEclsr3stdE7forwardIT_Efp_Efp0_Ecvv_EEOSG_RT0_
Line
Count
Source
11121
2
    {
11122
2
        ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
11123
2
    }
_ZN8nlohmann14adl_serializerINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEvE9from_jsonIRKNS_10basic_jsonISt3mapSt6vectorS6_blmdSaS0_EES6_EEDTcmclL_ZNS_12_GLOBAL__N_19from_jsonEEclsr3stdE7forwardIT_Efp_Efp0_Ecvv_EEOSG_RT0_
Line
Count
Source
11121
11.4k
    {
11122
11.4k
        ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
11123
11.4k
    }
_ZN8nlohmann14adl_serializerIivE9from_jsonIRKNS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaS0_EEiEEDTcmclL_ZNS_12_GLOBAL__N_19from_jsonEEclsr3stdE7forwardIT_Efp_Efp0_Ecvv_EEOSG_RT0_
Line
Count
Source
11121
152
    {
11122
152
        ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
11123
152
    }
_ZN8nlohmann14adl_serializerIdvE9from_jsonIRKNS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaS0_EEdEEDTcmclL_ZNS_12_GLOBAL__N_19from_jsonEEclsr3stdE7forwardIT_Efp_Efp0_Ecvv_EEOSG_RT0_
Line
Count
Source
11121
148
    {
11122
148
        ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
11123
148
    }
11124
11125
    /*!
11126
    @brief convert any value type to a JSON value
11127
11128
    This function is usually called by the constructors of the @ref basic_json
11129
    class.
11130
11131
    @param[in,out] j  JSON value to write to
11132
    @param[in] val     value to read from
11133
    */
11134
    template <typename BasicJsonType, typename ValueType>
11135
    static auto to_json(BasicJsonType& j, ValueType&& val) noexcept(
11136
        noexcept(::nlohmann::to_json(j, std::forward<ValueType>(val))))
11137
    -> decltype(::nlohmann::to_json(j, std::forward<ValueType>(val)),
11138
                void())
11139
207k
    {
11140
207k
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
11141
207k
    }
_ZN8nlohmann14adl_serializerINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEvE7to_jsonINS_10basic_jsonISt3mapSt6vectorS6_blmdSaS0_EERS6_EEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
Line
Count
Source
11139
62.5k
    {
11140
62.5k
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
11141
62.5k
    }
_ZN8nlohmann14adl_serializerIlvE7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaS0_EERlEEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
Line
Count
Source
11139
9.18k
    {
11140
9.18k
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
11141
9.18k
    }
_ZN8nlohmann14adl_serializerIbvE7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaS0_EERbEEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
Line
Count
Source
11139
602
    {
11140
602
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
11141
602
    }
_ZN8nlohmann14adl_serializerImvE7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaS0_EERmEEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
Line
Count
Source
11139
77.0k
    {
11140
77.0k
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
11141
77.0k
    }
_ZN8nlohmann14adl_serializerIdvE7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaS0_EERdEEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
Line
Count
Source
11139
57.4k
    {
11140
57.4k
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
11141
57.4k
    }
_ZN8nlohmann14adl_serializerIA474_cvE7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaS0_EERA474_KcEEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSI_
Line
Count
Source
11139
199
    {
11140
199
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
11141
199
    }
_ZN8nlohmann14adl_serializerINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEvE7to_jsonINS_10basic_jsonISt3mapSt6vectorS6_blmdSaS0_EES6_EEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSE_
Line
Count
Source
11139
423
    {
11140
423
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
11141
423
    }
_ZN8nlohmann14adl_serializerINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEvE7to_jsonINS_10basic_jsonISt3mapSt6vectorS6_blmdSaS0_EEKS6_EEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
Line
Count
Source
11139
47
    {
11140
47
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
11141
47
    }
_ZN8nlohmann14adl_serializerIjvE7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaS0_EERjEEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSF_
Line
Count
Source
11139
141
    {
11140
141
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
11141
141
    }
_ZN8nlohmann14adl_serializerIPKcvE7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaS0_EERKS2_EEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSI_
Line
Count
Source
11139
10
    {
11140
10
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
11141
10
    }
_ZN8nlohmann14adl_serializerIbvE7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaS0_EEbEEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSE_
Line
Count
Source
11139
1
    {
11140
1
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
11141
1
    }
_ZN8nlohmann14adl_serializerIdvE7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaS0_EEdEEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSE_
Line
Count
Source
11139
1
    {
11140
1
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
11141
1
    }
_ZN8nlohmann14adl_serializerIA6_cvE7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaS0_EERA6_KcEEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSI_
Line
Count
Source
11139
1
    {
11140
1
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
11141
1
    }
_ZN8nlohmann14adl_serializerIivE7to_jsonINS_10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaS0_EEiEEDTcmclL_ZNS_12_GLOBAL__N_17to_jsonEEfp_clsr3stdE7forwardIT0_Efp0_EEcvv_EERT_OSE_
Line
Count
Source
11139
1
    {
11140
1
        ::nlohmann::to_json(j, std::forward<ValueType>(val));
11141
1
    }
11142
};
11143
}
11144
11145
11146
/*!
11147
@brief namespace for Niels Lohmann
11148
@see https://github.com/nlohmann
11149
@since version 1.0.0
11150
*/
11151
namespace nlohmann
11152
{
11153
11154
/*!
11155
@brief a class to store JSON values
11156
11157
@tparam ObjectType type for JSON objects (`std::map` by default; will be used
11158
in @ref object_t)
11159
@tparam ArrayType type for JSON arrays (`std::vector` by default; will be used
11160
in @ref array_t)
11161
@tparam StringType type for JSON strings and object keys (`std::string` by
11162
default; will be used in @ref string_t)
11163
@tparam BooleanType type for JSON booleans (`bool` by default; will be used
11164
in @ref boolean_t)
11165
@tparam NumberIntegerType type for JSON integer numbers (`int64_t` by
11166
default; will be used in @ref number_integer_t)
11167
@tparam NumberUnsignedType type for JSON unsigned integer numbers (@c
11168
`uint64_t` by default; will be used in @ref number_unsigned_t)
11169
@tparam NumberFloatType type for JSON floating-point numbers (`double` by
11170
default; will be used in @ref number_float_t)
11171
@tparam AllocatorType type of the allocator to use (`std::allocator` by
11172
default)
11173
@tparam JSONSerializer the serializer to resolve internal calls to `to_json()`
11174
and `from_json()` (@ref adl_serializer by default)
11175
11176
@requirement The class satisfies the following concept requirements:
11177
- Basic
11178
 - [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible):
11179
   JSON values can be default constructed. The result will be a JSON null
11180
   value.
11181
 - [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible):
11182
   A JSON value can be constructed from an rvalue argument.
11183
 - [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible):
11184
   A JSON value can be copy-constructed from an lvalue expression.
11185
 - [MoveAssignable](https://en.cppreference.com/w/cpp/named_req/MoveAssignable):
11186
   A JSON value van be assigned from an rvalue argument.
11187
 - [CopyAssignable](https://en.cppreference.com/w/cpp/named_req/CopyAssignable):
11188
   A JSON value can be copy-assigned from an lvalue expression.
11189
 - [Destructible](https://en.cppreference.com/w/cpp/named_req/Destructible):
11190
   JSON values can be destructed.
11191
- Layout
11192
 - [StandardLayoutType](https://en.cppreference.com/w/cpp/named_req/StandardLayoutType):
11193
   JSON values have
11194
   [standard layout](https://en.cppreference.com/w/cpp/language/data_members#Standard_layout):
11195
   All non-static data members are private and standard layout types, the
11196
   class has no virtual functions or (virtual) base classes.
11197
- Library-wide
11198
 - [EqualityComparable](https://en.cppreference.com/w/cpp/named_req/EqualityComparable):
11199
   JSON values can be compared with `==`, see @ref
11200
   operator==(const_reference,const_reference).
11201
 - [LessThanComparable](https://en.cppreference.com/w/cpp/named_req/LessThanComparable):
11202
   JSON values can be compared with `<`, see @ref
11203
   operator<(const_reference,const_reference).
11204
 - [Swappable](https://en.cppreference.com/w/cpp/named_req/Swappable):
11205
   Any JSON lvalue or rvalue of can be swapped with any lvalue or rvalue of
11206
   other compatible types, using unqualified function call @ref swap().
11207
 - [NullablePointer](https://en.cppreference.com/w/cpp/named_req/NullablePointer):
11208
   JSON values can be compared against `std::nullptr_t` objects which are used
11209
   to model the `null` value.
11210
- Container
11211
 - [Container](https://en.cppreference.com/w/cpp/named_req/Container):
11212
   JSON values can be used like STL containers and provide iterator access.
11213
 - [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer);
11214
   JSON values can be used like STL containers and provide reverse iterator
11215
   access.
11216
11217
@invariant The member variables @a m_value and @a m_type have the following
11218
relationship:
11219
- If `m_type == value_t::object`, then `m_value.object != nullptr`.
11220
- If `m_type == value_t::array`, then `m_value.array != nullptr`.
11221
- If `m_type == value_t::string`, then `m_value.string != nullptr`.
11222
The invariants are checked by member function assert_invariant().
11223
11224
@internal
11225
@note ObjectType trick from http://stackoverflow.com/a/9860911
11226
@endinternal
11227
11228
@see [RFC 7159: The JavaScript Object Notation (JSON) Data Interchange
11229
Format](http://rfc7159.net/rfc7159)
11230
11231
@since version 1.0.0
11232
11233
@nosubgrouping
11234
*/
11235
NLOHMANN_BASIC_JSON_TPL_DECLARATION
11236
class basic_json
11237
{
11238
  private:
11239
    template<detail::value_t> friend struct detail::external_constructor;
11240
    friend ::nlohmann::json_pointer<basic_json>;
11241
    friend ::nlohmann::detail::parser<basic_json>;
11242
    friend ::nlohmann::detail::serializer<basic_json>;
11243
    template<typename BasicJsonType>
11244
    friend class ::nlohmann::detail::iter_impl;
11245
    template<typename BasicJsonType, typename CharType>
11246
    friend class ::nlohmann::detail::binary_writer;
11247
    template<typename BasicJsonType, typename SAX>
11248
    friend class ::nlohmann::detail::binary_reader;
11249
    template<typename BasicJsonType>
11250
    friend class ::nlohmann::detail::json_sax_dom_parser;
11251
    template<typename BasicJsonType>
11252
    friend class ::nlohmann::detail::json_sax_dom_callback_parser;
11253
11254
    /// workaround type for MSVC
11255
    using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
11256
11257
    // convenience aliases for types residing in namespace detail;
11258
    using lexer = ::nlohmann::detail::lexer<basic_json>;
11259
    using parser = ::nlohmann::detail::parser<basic_json>;
11260
11261
    using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
11262
    template<typename BasicJsonType>
11263
    using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
11264
    template<typename BasicJsonType>
11265
    using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
11266
    template<typename Iterator>
11267
    using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
11268
    template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
11269
11270
    template<typename CharType>
11271
    using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
11272
11273
    using binary_reader = ::nlohmann::detail::binary_reader<basic_json>;
11274
    template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
11275
11276
    using serializer = ::nlohmann::detail::serializer<basic_json>;
11277
11278
  public:
11279
    using value_t = detail::value_t;
11280
    /// JSON Pointer, see @ref nlohmann::json_pointer
11281
    using json_pointer = ::nlohmann::json_pointer<basic_json>;
11282
    template<typename T, typename SFINAE>
11283
    using json_serializer = JSONSerializer<T, SFINAE>;
11284
    /// helper type for initializer lists of basic_json values
11285
    using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
11286
11287
    using input_format_t = detail::input_format_t;
11288
    /// SAX interface type, see @ref nlohmann::json_sax
11289
    using json_sax_t = json_sax<basic_json>;
11290
11291
    ////////////////
11292
    // exceptions //
11293
    ////////////////
11294
11295
    /// @name exceptions
11296
    /// Classes to implement user-defined exceptions.
11297
    /// @{
11298
11299
    /// @copydoc detail::exception
11300
    using exception = detail::exception;
11301
    /// @copydoc detail::parse_error
11302
    using parse_error = detail::parse_error;
11303
    /// @copydoc detail::invalid_iterator
11304
    using invalid_iterator = detail::invalid_iterator;
11305
    /// @copydoc detail::type_error
11306
    using type_error = detail::type_error;
11307
    /// @copydoc detail::out_of_range
11308
    using out_of_range = detail::out_of_range;
11309
    /// @copydoc detail::other_error
11310
    using other_error = detail::other_error;
11311
11312
    /// @}
11313
11314
11315
    /////////////////////
11316
    // container types //
11317
    /////////////////////
11318
11319
    /// @name container types
11320
    /// The canonic container types to use @ref basic_json like any other STL
11321
    /// container.
11322
    /// @{
11323
11324
    /// the type of elements in a basic_json container
11325
    using value_type = basic_json;
11326
11327
    /// the type of an element reference
11328
    using reference = value_type&;
11329
    /// the type of an element const reference
11330
    using const_reference = const value_type&;
11331
11332
    /// a type to represent differences between iterators
11333
    using difference_type = std::ptrdiff_t;
11334
    /// a type to represent container sizes
11335
    using size_type = std::size_t;
11336
11337
    /// the allocator type
11338
    using allocator_type = AllocatorType<basic_json>;
11339
11340
    /// the type of an element pointer
11341
    using pointer = typename std::allocator_traits<allocator_type>::pointer;
11342
    /// the type of an element const pointer
11343
    using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
11344
11345
    /// an iterator for a basic_json container
11346
    using iterator = iter_impl<basic_json>;
11347
    /// a const iterator for a basic_json container
11348
    using const_iterator = iter_impl<const basic_json>;
11349
    /// a reverse iterator for a basic_json container
11350
    using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
11351
    /// a const reverse iterator for a basic_json container
11352
    using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
11353
11354
    /// @}
11355
11356
11357
    /*!
11358
    @brief returns the allocator associated with the container
11359
    */
11360
    static allocator_type get_allocator()
11361
    {
11362
        return allocator_type();
11363
    }
11364
11365
    /*!
11366
    @brief returns version information on the library
11367
11368
    This function returns a JSON object with information about the library,
11369
    including the version number and information on the platform and compiler.
11370
11371
    @return JSON object holding version information
11372
    key         | description
11373
    ----------- | ---------------
11374
    `compiler`  | Information on the used compiler. It is an object with the following keys: `c++` (the used C++ standard), `family` (the compiler family; possible values are `clang`, `icc`, `gcc`, `ilecpp`, `msvc`, `pgcpp`, `sunpro`, and `unknown`), and `version` (the compiler version).
11375
    `copyright` | The copyright line for the library as string.
11376
    `name`      | The name of the library as string.
11377
    `platform`  | The used platform as string. Possible values are `win32`, `linux`, `apple`, `unix`, and `unknown`.
11378
    `url`       | The URL of the project as string.
11379
    `version`   | The version of the library. It is an object with the following keys: `major`, `minor`, and `patch` as defined by [Semantic Versioning](http://semver.org), and `string` (the version string).
11380
11381
    @liveexample{The following code shows an example output of the `meta()`
11382
    function.,meta}
11383
11384
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
11385
    changes to any JSON value.
11386
11387
    @complexity Constant.
11388
11389
    @since 2.1.0
11390
    */
11391
    static basic_json meta()
11392
    {
11393
        basic_json result;
11394
11395
        result["copyright"] = "(C) 2013-2017 Niels Lohmann";
11396
        result["name"] = "JSON for Modern C++";
11397
        result["url"] = "https://github.com/nlohmann/json";
11398
        result["version"]["string"] =
11399
            std::to_string(NLOHMANN_JSON_VERSION_MAJOR) + "." +
11400
            std::to_string(NLOHMANN_JSON_VERSION_MINOR) + "." +
11401
            std::to_string(NLOHMANN_JSON_VERSION_PATCH);
11402
        result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
11403
        result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
11404
        result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
11405
11406
#ifdef _WIN32
11407
        result["platform"] = "win32";
11408
#elif defined __linux__
11409
        result["platform"] = "linux";
11410
#elif defined __APPLE__
11411
        result["platform"] = "apple";
11412
#elif defined __unix__
11413
        result["platform"] = "unix";
11414
#else
11415
        result["platform"] = "unknown";
11416
#endif
11417
11418
#if defined(__ICC) || defined(__INTEL_COMPILER)
11419
        result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
11420
#elif defined(__clang__)
11421
        result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
11422
#elif defined(__GNUC__) || defined(__GNUG__)
11423
        result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}};
11424
#elif defined(__HP_cc) || defined(__HP_aCC)
11425
        result["compiler"] = "hp"
11426
#elif defined(__IBMCPP__)
11427
        result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
11428
#elif defined(_MSC_VER)
11429
        result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
11430
#elif defined(__PGI)
11431
        result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
11432
#elif defined(__SUNPRO_CC)
11433
        result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
11434
#else
11435
        result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
11436
#endif
11437
11438
#ifdef __cplusplus
11439
        result["compiler"]["c++"] = std::to_string(__cplusplus);
11440
#else
11441
        result["compiler"]["c++"] = "unknown";
11442
#endif
11443
        return result;
11444
    }
11445
11446
11447
    ///////////////////////////
11448
    // JSON value data types //
11449
    ///////////////////////////
11450
11451
    /// @name JSON value data types
11452
    /// The data types to store a JSON value. These types are derived from
11453
    /// the template arguments passed to class @ref basic_json.
11454
    /// @{
11455
11456
#if defined(JSON_HAS_CPP_14)
11457
    // Use transparent comparator if possible, combined with perfect forwarding
11458
    // on find() and count() calls prevents unnecessary string construction.
11459
    using object_comparator_t = std::less<>;
11460
#else
11461
    using object_comparator_t = std::less<StringType>;
11462
#endif
11463
11464
    /*!
11465
    @brief a type for an object
11466
11467
    [RFC 7159](http://rfc7159.net/rfc7159) describes JSON objects as follows:
11468
    > An object is an unordered collection of zero or more name/value pairs,
11469
    > where a name is a string and a value is a string, number, boolean, null,
11470
    > object, or array.
11471
11472
    To store objects in C++, a type is defined by the template parameters
11473
    described below.
11474
11475
    @tparam ObjectType  the container to store objects (e.g., `std::map` or
11476
    `std::unordered_map`)
11477
    @tparam StringType the type of the keys or names (e.g., `std::string`).
11478
    The comparison function `std::less<StringType>` is used to order elements
11479
    inside the container.
11480
    @tparam AllocatorType the allocator to use for objects (e.g.,
11481
    `std::allocator`)
11482
11483
    #### Default type
11484
11485
    With the default values for @a ObjectType (`std::map`), @a StringType
11486
    (`std::string`), and @a AllocatorType (`std::allocator`), the default
11487
    value for @a object_t is:
11488
11489
    @code {.cpp}
11490
    std::map<
11491
      std::string, // key_type
11492
      basic_json, // value_type
11493
      std::less<std::string>, // key_compare
11494
      std::allocator<std::pair<const std::string, basic_json>> // allocator_type
11495
    >
11496
    @endcode
11497
11498
    #### Behavior
11499
11500
    The choice of @a object_t influences the behavior of the JSON class. With
11501
    the default type, objects have the following behavior:
11502
11503
    - When all names are unique, objects will be interoperable in the sense
11504
      that all software implementations receiving that object will agree on
11505
      the name-value mappings.
11506
    - When the names within an object are not unique, it is unspecified which
11507
      one of the values for a given key will be chosen. For instance,
11508
      `{"key": 2, "key": 1}` could be equal to either `{"key": 1}` or
11509
      `{"key": 2}`.
11510
    - Internally, name/value pairs are stored in lexicographical order of the
11511
      names. Objects will also be serialized (see @ref dump) in this order.
11512
      For instance, `{"b": 1, "a": 2}` and `{"a": 2, "b": 1}` will be stored
11513
      and serialized as `{"a": 2, "b": 1}`.
11514
    - When comparing objects, the order of the name/value pairs is irrelevant.
11515
      This makes objects interoperable in the sense that they will not be
11516
      affected by these differences. For instance, `{"b": 1, "a": 2}` and
11517
      `{"a": 2, "b": 1}` will be treated as equal.
11518
11519
    #### Limits
11520
11521
    [RFC 7159](http://rfc7159.net/rfc7159) specifies:
11522
    > An implementation may set limits on the maximum depth of nesting.
11523
11524
    In this class, the object's limit of nesting is not explicitly constrained.
11525
    However, a maximum depth of nesting may be introduced by the compiler or
11526
    runtime environment. A theoretical limit can be queried by calling the
11527
    @ref max_size function of a JSON object.
11528
11529
    #### Storage
11530
11531
    Objects are stored as pointers in a @ref basic_json type. That is, for any
11532
    access to object values, a pointer of type `object_t*` must be
11533
    dereferenced.
11534
11535
    @sa @ref array_t -- type for an array value
11536
11537
    @since version 1.0.0
11538
11539
    @note The order name/value pairs are added to the object is *not*
11540
    preserved by the library. Therefore, iterating an object may return
11541
    name/value pairs in a different order than they were originally stored. In
11542
    fact, keys will be traversed in alphabetical order as `std::map` with
11543
    `std::less` is used by default. Please note this behavior conforms to [RFC
11544
    7159](http://rfc7159.net/rfc7159), because any order implements the
11545
    specified "unordered" nature of JSON objects.
11546
    */
11547
    using object_t = ObjectType<StringType,
11548
          basic_json,
11549
          object_comparator_t,
11550
          AllocatorType<std::pair<const StringType,
11551
          basic_json>>>;
11552
11553
    /*!
11554
    @brief a type for an array
11555
11556
    [RFC 7159](http://rfc7159.net/rfc7159) describes JSON arrays as follows:
11557
    > An array is an ordered sequence of zero or more values.
11558
11559
    To store objects in C++, a type is defined by the template parameters
11560
    explained below.
11561
11562
    @tparam ArrayType  container type to store arrays (e.g., `std::vector` or
11563
    `std::list`)
11564
    @tparam AllocatorType allocator to use for arrays (e.g., `std::allocator`)
11565
11566
    #### Default type
11567
11568
    With the default values for @a ArrayType (`std::vector`) and @a
11569
    AllocatorType (`std::allocator`), the default value for @a array_t is:
11570
11571
    @code {.cpp}
11572
    std::vector<
11573
      basic_json, // value_type
11574
      std::allocator<basic_json> // allocator_type
11575
    >
11576
    @endcode
11577
11578
    #### Limits
11579
11580
    [RFC 7159](http://rfc7159.net/rfc7159) specifies:
11581
    > An implementation may set limits on the maximum depth of nesting.
11582
11583
    In this class, the array's limit of nesting is not explicitly constrained.
11584
    However, a maximum depth of nesting may be introduced by the compiler or
11585
    runtime environment. A theoretical limit can be queried by calling the
11586
    @ref max_size function of a JSON array.
11587
11588
    #### Storage
11589
11590
    Arrays are stored as pointers in a @ref basic_json type. That is, for any
11591
    access to array values, a pointer of type `array_t*` must be dereferenced.
11592
11593
    @sa @ref object_t -- type for an object value
11594
11595
    @since version 1.0.0
11596
    */
11597
    using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
11598
11599
    /*!
11600
    @brief a type for a string
11601
11602
    [RFC 7159](http://rfc7159.net/rfc7159) describes JSON strings as follows:
11603
    > A string is a sequence of zero or more Unicode characters.
11604
11605
    To store objects in C++, a type is defined by the template parameter
11606
    described below. Unicode values are split by the JSON class into
11607
    byte-sized characters during deserialization.
11608
11609
    @tparam StringType  the container to store strings (e.g., `std::string`).
11610
    Note this container is used for keys/names in objects, see @ref object_t.
11611
11612
    #### Default type
11613
11614
    With the default values for @a StringType (`std::string`), the default
11615
    value for @a string_t is:
11616
11617
    @code {.cpp}
11618
    std::string
11619
    @endcode
11620
11621
    #### Encoding
11622
11623
    Strings are stored in UTF-8 encoding. Therefore, functions like
11624
    `std::string::size()` or `std::string::length()` return the number of
11625
    bytes in the string rather than the number of characters or glyphs.
11626
11627
    #### String comparison
11628
11629
    [RFC 7159](http://rfc7159.net/rfc7159) states:
11630
    > Software implementations are typically required to test names of object
11631
    > members for equality. Implementations that transform the textual
11632
    > representation into sequences of Unicode code units and then perform the
11633
    > comparison numerically, code unit by code unit, are interoperable in the
11634
    > sense that implementations will agree in all cases on equality or
11635
    > inequality of two strings. For example, implementations that compare
11636
    > strings with escaped characters unconverted may incorrectly find that
11637
    > `"a\\b"` and `"a\u005Cb"` are not equal.
11638
11639
    This implementation is interoperable as it does compare strings code unit
11640
    by code unit.
11641
11642
    #### Storage
11643
11644
    String values are stored as pointers in a @ref basic_json type. That is,
11645
    for any access to string values, a pointer of type `string_t*` must be
11646
    dereferenced.
11647
11648
    @since version 1.0.0
11649
    */
11650
    using string_t = StringType;
11651
11652
    /*!
11653
    @brief a type for a boolean
11654
11655
    [RFC 7159](http://rfc7159.net/rfc7159) implicitly describes a boolean as a
11656
    type which differentiates the two literals `true` and `false`.
11657
11658
    To store objects in C++, a type is defined by the template parameter @a
11659
    BooleanType which chooses the type to use.
11660
11661
    #### Default type
11662
11663
    With the default values for @a BooleanType (`bool`), the default value for
11664
    @a boolean_t is:
11665
11666
    @code {.cpp}
11667
    bool
11668
    @endcode
11669
11670
    #### Storage
11671
11672
    Boolean values are stored directly inside a @ref basic_json type.
11673
11674
    @since version 1.0.0
11675
    */
11676
    using boolean_t = BooleanType;
11677
11678
    /*!
11679
    @brief a type for a number (integer)
11680
11681
    [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:
11682
    > The representation of numbers is similar to that used in most
11683
    > programming languages. A number is represented in base 10 using decimal
11684
    > digits. It contains an integer component that may be prefixed with an
11685
    > optional minus sign, which may be followed by a fraction part and/or an
11686
    > exponent part. Leading zeros are not allowed. (...) Numeric values that
11687
    > cannot be represented in the grammar below (such as Infinity and NaN)
11688
    > are not permitted.
11689
11690
    This description includes both integer and floating-point numbers.
11691
    However, C++ allows more precise storage if it is known whether the number
11692
    is a signed integer, an unsigned integer or a floating-point number.
11693
    Therefore, three different types, @ref number_integer_t, @ref
11694
    number_unsigned_t and @ref number_float_t are used.
11695
11696
    To store integer numbers in C++, a type is defined by the template
11697
    parameter @a NumberIntegerType which chooses the type to use.
11698
11699
    #### Default type
11700
11701
    With the default values for @a NumberIntegerType (`int64_t`), the default
11702
    value for @a number_integer_t is:
11703
11704
    @code {.cpp}
11705
    int64_t
11706
    @endcode
11707
11708
    #### Default behavior
11709
11710
    - The restrictions about leading zeros is not enforced in C++. Instead,
11711
      leading zeros in integer literals lead to an interpretation as octal
11712
      number. Internally, the value will be stored as decimal number. For
11713
      instance, the C++ integer literal `010` will be serialized to `8`.
11714
      During deserialization, leading zeros yield an error.
11715
    - Not-a-number (NaN) values will be serialized to `null`.
11716
11717
    #### Limits
11718
11719
    [RFC 7159](http://rfc7159.net/rfc7159) specifies:
11720
    > An implementation may set limits on the range and precision of numbers.
11721
11722
    When the default type is used, the maximal integer number that can be
11723
    stored is `9223372036854775807` (INT64_MAX) and the minimal integer number
11724
    that can be stored is `-9223372036854775808` (INT64_MIN). Integer numbers
11725
    that are out of range will yield over/underflow when used in a
11726
    constructor. During deserialization, too large or small integer numbers
11727
    will be automatically be stored as @ref number_unsigned_t or @ref
11728
    number_float_t.
11729
11730
    [RFC 7159](http://rfc7159.net/rfc7159) further states:
11731
    > Note that when such software is used, numbers that are integers and are
11732
    > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense
11733
    > that implementations will agree exactly on their numeric values.
11734
11735
    As this range is a subrange of the exactly supported range [INT64_MIN,
11736
    INT64_MAX], this class's integer type is interoperable.
11737
11738
    #### Storage
11739
11740
    Integer number values are stored directly inside a @ref basic_json type.
11741
11742
    @sa @ref number_float_t -- type for number values (floating-point)
11743
11744
    @sa @ref number_unsigned_t -- type for number values (unsigned integer)
11745
11746
    @since version 1.0.0
11747
    */
11748
    using number_integer_t = NumberIntegerType;
11749
11750
    /*!
11751
    @brief a type for a number (unsigned)
11752
11753
    [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:
11754
    > The representation of numbers is similar to that used in most
11755
    > programming languages. A number is represented in base 10 using decimal
11756
    > digits. It contains an integer component that may be prefixed with an
11757
    > optional minus sign, which may be followed by a fraction part and/or an
11758
    > exponent part. Leading zeros are not allowed. (...) Numeric values that
11759
    > cannot be represented in the grammar below (such as Infinity and NaN)
11760
    > are not permitted.
11761
11762
    This description includes both integer and floating-point numbers.
11763
    However, C++ allows more precise storage if it is known whether the number
11764
    is a signed integer, an unsigned integer or a floating-point number.
11765
    Therefore, three different types, @ref number_integer_t, @ref
11766
    number_unsigned_t and @ref number_float_t are used.
11767
11768
    To store unsigned integer numbers in C++, a type is defined by the
11769
    template parameter @a NumberUnsignedType which chooses the type to use.
11770
11771
    #### Default type
11772
11773
    With the default values for @a NumberUnsignedType (`uint64_t`), the
11774
    default value for @a number_unsigned_t is:
11775
11776
    @code {.cpp}
11777
    uint64_t
11778
    @endcode
11779
11780
    #### Default behavior
11781
11782
    - The restrictions about leading zeros is not enforced in C++. Instead,
11783
      leading zeros in integer literals lead to an interpretation as octal
11784
      number. Internally, the value will be stored as decimal number. For
11785
      instance, the C++ integer literal `010` will be serialized to `8`.
11786
      During deserialization, leading zeros yield an error.
11787
    - Not-a-number (NaN) values will be serialized to `null`.
11788
11789
    #### Limits
11790
11791
    [RFC 7159](http://rfc7159.net/rfc7159) specifies:
11792
    > An implementation may set limits on the range and precision of numbers.
11793
11794
    When the default type is used, the maximal integer number that can be
11795
    stored is `18446744073709551615` (UINT64_MAX) and the minimal integer
11796
    number that can be stored is `0`. Integer numbers that are out of range
11797
    will yield over/underflow when used in a constructor. During
11798
    deserialization, too large or small integer numbers will be automatically
11799
    be stored as @ref number_integer_t or @ref number_float_t.
11800
11801
    [RFC 7159](http://rfc7159.net/rfc7159) further states:
11802
    > Note that when such software is used, numbers that are integers and are
11803
    > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense
11804
    > that implementations will agree exactly on their numeric values.
11805
11806
    As this range is a subrange (when considered in conjunction with the
11807
    number_integer_t type) of the exactly supported range [0, UINT64_MAX],
11808
    this class's integer type is interoperable.
11809
11810
    #### Storage
11811
11812
    Integer number values are stored directly inside a @ref basic_json type.
11813
11814
    @sa @ref number_float_t -- type for number values (floating-point)
11815
    @sa @ref number_integer_t -- type for number values (integer)
11816
11817
    @since version 2.0.0
11818
    */
11819
    using number_unsigned_t = NumberUnsignedType;
11820
11821
    /*!
11822
    @brief a type for a number (floating-point)
11823
11824
    [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:
11825
    > The representation of numbers is similar to that used in most
11826
    > programming languages. A number is represented in base 10 using decimal
11827
    > digits. It contains an integer component that may be prefixed with an
11828
    > optional minus sign, which may be followed by a fraction part and/or an
11829
    > exponent part. Leading zeros are not allowed. (...) Numeric values that
11830
    > cannot be represented in the grammar below (such as Infinity and NaN)
11831
    > are not permitted.
11832
11833
    This description includes both integer and floating-point numbers.
11834
    However, C++ allows more precise storage if it is known whether the number
11835
    is a signed integer, an unsigned integer or a floating-point number.
11836
    Therefore, three different types, @ref number_integer_t, @ref
11837
    number_unsigned_t and @ref number_float_t are used.
11838
11839
    To store floating-point numbers in C++, a type is defined by the template
11840
    parameter @a NumberFloatType which chooses the type to use.
11841
11842
    #### Default type
11843
11844
    With the default values for @a NumberFloatType (`double`), the default
11845
    value for @a number_float_t is:
11846
11847
    @code {.cpp}
11848
    double
11849
    @endcode
11850
11851
    #### Default behavior
11852
11853
    - The restrictions about leading zeros is not enforced in C++. Instead,
11854
      leading zeros in floating-point literals will be ignored. Internally,
11855
      the value will be stored as decimal number. For instance, the C++
11856
      floating-point literal `01.2` will be serialized to `1.2`. During
11857
      deserialization, leading zeros yield an error.
11858
    - Not-a-number (NaN) values will be serialized to `null`.
11859
11860
    #### Limits
11861
11862
    [RFC 7159](http://rfc7159.net/rfc7159) states:
11863
    > This specification allows implementations to set limits on the range and
11864
    > precision of numbers accepted. Since software that implements IEEE
11865
    > 754-2008 binary64 (double precision) numbers is generally available and
11866
    > widely used, good interoperability can be achieved by implementations
11867
    > that expect no more precision or range than these provide, in the sense
11868
    > that implementations will approximate JSON numbers within the expected
11869
    > precision.
11870
11871
    This implementation does exactly follow this approach, as it uses double
11872
    precision floating-point numbers. Note values smaller than
11873
    `-1.79769313486232e+308` and values greater than `1.79769313486232e+308`
11874
    will be stored as NaN internally and be serialized to `null`.
11875
11876
    #### Storage
11877
11878
    Floating-point number values are stored directly inside a @ref basic_json
11879
    type.
11880
11881
    @sa @ref number_integer_t -- type for number values (integer)
11882
11883
    @sa @ref number_unsigned_t -- type for number values (unsigned integer)
11884
11885
    @since version 1.0.0
11886
    */
11887
    using number_float_t = NumberFloatType;
11888
11889
    /// @}
11890
11891
  private:
11892
11893
    /// helper for exception-safe object creation
11894
    template<typename T, typename... Args>
11895
    static T* create(Args&& ... args)
11896
151k
    {
11897
151k
        AllocatorType<T> alloc;
11898
151k
        using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
11899
151k
11900
151k
        auto deleter = [&](T * object)
11901
151k
        {
11902
0
            AllocatorTraits::deallocate(alloc, object, 1);
11903
0
        };
Unexecuted instantiation: _ZZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE6createIS1_IS8_SA_St4lessIvESaISt4pairIKS8_SA_EEEJEEEPT_DpOT0_ENKUlPSI_E_clESJ_
Unexecuted instantiation: _ZZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE6createIS2_ISA_SaISA_EEJEEEPT_DpOT0_ENKUlPSD_E_clESE_
Unexecuted instantiation: _ZZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE6createIS8_JRA1_KcEEEPT_DpOT0_ENKUlPS8_E_clESF_
Unexecuted instantiation: _ZZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE6createIS1_IS8_SA_St4lessIvESaISt4pairIKS8_SA_EEEJRKSI_EEEPT_DpOT0_ENKUlPSI_E_clESL_
Unexecuted instantiation: _ZZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE6createIS2_ISA_SaISA_EEJRKSD_EEEPT_DpOT0_ENKUlPSD_E_clESG_
Unexecuted instantiation: _ZZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE6createIS8_JRKS8_EEEPT_DpOT0_ENKUlPS8_E_clESE_
Unexecuted instantiation: _ZZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE6createIS8_JRA474_KcEEEPT_DpOT0_ENKUlPS8_E_clESF_
Unexecuted instantiation: _ZZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE6createIS8_JS8_EEEPT_DpOT0_ENKUlPS8_E_clESC_
Unexecuted instantiation: _ZZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE6createIS8_JRKPKcEEEPT_DpOT0_ENKUlPS8_E_clESG_
Unexecuted instantiation: _ZZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE6createIS8_JRA6_KcEEEPT_DpOT0_ENKUlPS8_E_clESF_
11904
151k
        std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
11905
151k
        AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
11906
151k
        assert(object != nullptr);
11907
151k
        return object.release();
11908
151k
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE6createIS1_IS8_SA_St4lessIvESaISt4pairIKS8_SA_EEEJEEEPT_DpOT0_
Line
Count
Source
11896
51.2k
    {
11897
51.2k
        AllocatorType<T> alloc;
11898
51.2k
        using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
11899
51.2k
11900
51.2k
        auto deleter = [&](T * object)
11901
51.2k
        {
11902
51.2k
            AllocatorTraits::deallocate(alloc, object, 1);
11903
51.2k
        };
11904
51.2k
        std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
11905
51.2k
        AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
11906
51.2k
        assert(object != nullptr);
11907
51.2k
        return object.release();
11908
51.2k
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE6createIS2_ISA_SaISA_EEJEEEPT_DpOT0_
Line
Count
Source
11896
601
    {
11897
601
        AllocatorType<T> alloc;
11898
601
        using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
11899
601
11900
601
        auto deleter = [&](T * object)
11901
601
        {
11902
601
            AllocatorTraits::deallocate(alloc, object, 1);
11903
601
        };
11904
601
        std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
11905
601
        AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
11906
601
        assert(object != nullptr);
11907
601
        return object.release();
11908
601
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE6createIS2_ISA_SaISA_EEJRKSD_EEEPT_DpOT0_
Line
Count
Source
11896
24
    {
11897
24
        AllocatorType<T> alloc;
11898
24
        using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
11899
24
11900
24
        auto deleter = [&](T * object)
11901
24
        {
11902
24
            AllocatorTraits::deallocate(alloc, object, 1);
11903
24
        };
11904
24
        std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
11905
24
        AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
11906
24
        assert(object != nullptr);
11907
24
        return object.release();
11908
24
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE6createIS8_JRKS8_EEEPT_DpOT0_
Line
Count
Source
11896
92.9k
    {
11897
92.9k
        AllocatorType<T> alloc;
11898
92.9k
        using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
11899
92.9k
11900
92.9k
        auto deleter = [&](T * object)
11901
92.9k
        {
11902
92.9k
            AllocatorTraits::deallocate(alloc, object, 1);
11903
92.9k
        };
11904
92.9k
        std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
11905
92.9k
        AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
11906
92.9k
        assert(object != nullptr);
11907
92.9k
        return object.release();
11908
92.9k
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE6createIS1_IS8_SA_St4lessIvESaISt4pairIKS8_SA_EEEJRKSI_EEEPT_DpOT0_
Line
Count
Source
11896
5.79k
    {
11897
5.79k
        AllocatorType<T> alloc;
11898
5.79k
        using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
11899
5.79k
11900
5.79k
        auto deleter = [&](T * object)
11901
5.79k
        {
11902
5.79k
            AllocatorTraits::deallocate(alloc, object, 1);
11903
5.79k
        };
11904
5.79k
        std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
11905
5.79k
        AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
11906
5.79k
        assert(object != nullptr);
11907
5.79k
        return object.release();
11908
5.79k
    }
Unexecuted instantiation: _ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE6createIS8_JRA1_KcEEEPT_DpOT0_
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE6createIS8_JRA474_KcEEEPT_DpOT0_
Line
Count
Source
11896
199
    {
11897
199
        AllocatorType<T> alloc;
11898
199
        using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
11899
199
11900
199
        auto deleter = [&](T * object)
11901
199
        {
11902
199
            AllocatorTraits::deallocate(alloc, object, 1);
11903
199
        };
11904
199
        std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
11905
199
        AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
11906
199
        assert(object != nullptr);
11907
199
        return object.release();
11908
199
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE6createIS8_JS8_EEEPT_DpOT0_
Line
Count
Source
11896
423
    {
11897
423
        AllocatorType<T> alloc;
11898
423
        using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
11899
423
11900
423
        auto deleter = [&](T * object)
11901
423
        {
11902
423
            AllocatorTraits::deallocate(alloc, object, 1);
11903
423
        };
11904
423
        std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
11905
423
        AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
11906
423
        assert(object != nullptr);
11907
423
        return object.release();
11908
423
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE6createIS8_JRKPKcEEEPT_DpOT0_
Line
Count
Source
11896
10
    {
11897
10
        AllocatorType<T> alloc;
11898
10
        using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
11899
10
11900
10
        auto deleter = [&](T * object)
11901
10
        {
11902
10
            AllocatorTraits::deallocate(alloc, object, 1);
11903
10
        };
11904
10
        std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
11905
10
        AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
11906
10
        assert(object != nullptr);
11907
10
        return object.release();
11908
10
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE6createIS8_JRA6_KcEEEPT_DpOT0_
Line
Count
Source
11896
1
    {
11897
1
        AllocatorType<T> alloc;
11898
1
        using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
11899
1
11900
1
        auto deleter = [&](T * object)
11901
1
        {
11902
1
            AllocatorTraits::deallocate(alloc, object, 1);
11903
1
        };
11904
1
        std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
11905
1
        AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
11906
1
        assert(object != nullptr);
11907
1
        return object.release();
11908
1
    }
11909
11910
    ////////////////////////
11911
    // JSON value storage //
11912
    ////////////////////////
11913
11914
    /*!
11915
    @brief a JSON value
11916
11917
    The actual storage for a JSON value of the @ref basic_json class. This
11918
    union combines the different storage types for the JSON value types
11919
    defined in @ref value_t.
11920
11921
    JSON type | value_t type    | used type
11922
    --------- | --------------- | ------------------------
11923
    object    | object          | pointer to @ref object_t
11924
    array     | array           | pointer to @ref array_t
11925
    string    | string          | pointer to @ref string_t
11926
    boolean   | boolean         | @ref boolean_t
11927
    number    | number_integer  | @ref number_integer_t
11928
    number    | number_unsigned | @ref number_unsigned_t
11929
    number    | number_float    | @ref number_float_t
11930
    null      | null            | *no value is stored*
11931
11932
    @note Variable-length types (objects, arrays, and strings) are stored as
11933
    pointers. The size of the union should not exceed 64 bits if the default
11934
    value types are used.
11935
11936
    @since version 1.0.0
11937
    */
11938
    union json_value
11939
    {
11940
        /// object (stored with pointer to save storage)
11941
        object_t* object;
11942
        /// array (stored with pointer to save storage)
11943
        array_t* array;
11944
        /// string (stored with pointer to save storage)
11945
        string_t* string;
11946
        /// boolean
11947
        boolean_t boolean;
11948
        /// number (integer)
11949
        number_integer_t number_integer;
11950
        /// number (unsigned integer)
11951
        number_unsigned_t number_unsigned;
11952
        /// number (floating-point)
11953
        number_float_t number_float;
11954
11955
        /// default constructor (for null values)
11956
        json_value() = default;
11957
        /// constructor for booleans
11958
615
        json_value(boolean_t v) noexcept : boolean(v) {}
Unexecuted instantiation: _ZN8nlohmann10basic_json10json_valueC2ET2_
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE10json_valueC2Eb
Line
Count
Source
11958
615
        json_value(boolean_t v) noexcept : boolean(v) {}
11959
        /// constructor for numbers (integer)
11960
9.60k
        json_value(number_integer_t v) noexcept : number_integer(v) {}
Unexecuted instantiation: _ZN8nlohmann10basic_json10json_valueC2ET3_
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE10json_valueC2El
Line
Count
Source
11960
9.60k
        json_value(number_integer_t v) noexcept : number_integer(v) {}
11961
        /// constructor for numbers (unsigned)
11962
80.8k
        json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
Unexecuted instantiation: _ZN8nlohmann10basic_json10json_valueC2ET4_
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE10json_valueC2Em
Line
Count
Source
11962
80.8k
        json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
11963
        /// constructor for numbers (floating-point)
11964
60.1k
        json_value(number_float_t v) noexcept : number_float(v) {}
Unexecuted instantiation: _ZN8nlohmann10basic_json10json_valueC2ET5_
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE10json_valueC2Ed
Line
Count
Source
11964
60.1k
        json_value(number_float_t v) noexcept : number_float(v) {}
11965
        /// constructor for empty values of a given type
11966
        json_value(value_t t)
11967
302k
        {
11968
302k
            switch (t)
11969
302k
            {
11970
302k
                case value_t::object:
11971
51.1k
                {
11972
51.1k
                    object = create<object_t>();
11973
51.1k
                    break;
11974
51.1k
                }
11975
51.1k
11976
51.1k
                case value_t::array:
11977
601
                {
11978
601
                    array = create<array_t>();
11979
601
                    break;
11980
51.1k
                }
11981
51.1k
11982
51.1k
                case value_t::string:
11983
0
                {
11984
0
                    string = create<string_t>("");
11985
0
                    break;
11986
51.1k
                }
11987
51.1k
11988
51.1k
                case value_t::boolean:
11989
0
                {
11990
0
                    boolean = boolean_t(false);
11991
0
                    break;
11992
51.1k
                }
11993
51.1k
11994
51.1k
                case value_t::number_integer:
11995
0
                {
11996
0
                    number_integer = number_integer_t(0);
11997
0
                    break;
11998
51.1k
                }
11999
51.1k
12000
51.1k
                case value_t::number_unsigned:
12001
0
                {
12002
0
                    number_unsigned = number_unsigned_t(0);
12003
0
                    break;
12004
51.1k
                }
12005
51.1k
12006
51.1k
                case value_t::number_float:
12007
0
                {
12008
0
                    number_float = number_float_t(0.0);
12009
0
                    break;
12010
51.1k
                }
12011
51.1k
12012
251k
                case value_t::null:
12013
251k
                {
12014
251k
                    object = nullptr;  // silence warning, see #821
12015
251k
                    break;
12016
51.1k
                }
12017
51.1k
12018
51.1k
                default:
12019
0
                {
12020
0
                    object = nullptr;  // silence warning, see #821
12021
0
                    if (JSON_UNLIKELY(t == value_t::null))
12022
0
                    {
12023
0
                        JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.2.0")); // LCOV_EXCL_LINE
12024
0
                    }
12025
0
                    break;
12026
0
                }
12027
302k
            }
12028
302k
        }
Unexecuted instantiation: _ZN8nlohmann10basic_json10json_valueC2ENS_6detail7value_tE
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE10json_valueC2ENS_6detail7value_tE
Line
Count
Source
11967
302k
        {
11968
302k
            switch (t)
11969
302k
            {
11970
302k
                case value_t::object:
11971
51.1k
                {
11972
51.1k
                    object = create<object_t>();
11973
51.1k
                    break;
11974
51.1k
                }
11975
51.1k
11976
51.1k
                case value_t::array:
11977
601
                {
11978
601
                    array = create<array_t>();
11979
601
                    break;
11980
51.1k
                }
11981
51.1k
11982
51.1k
                case value_t::string:
11983
0
                {
11984
0
                    string = create<string_t>("");
11985
0
                    break;
11986
51.1k
                }
11987
51.1k
11988
51.1k
                case value_t::boolean:
11989
0
                {
11990
0
                    boolean = boolean_t(false);
11991
0
                    break;
11992
51.1k
                }
11993
51.1k
11994
51.1k
                case value_t::number_integer:
11995
0
                {
11996
0
                    number_integer = number_integer_t(0);
11997
0
                    break;
11998
51.1k
                }
11999
51.1k
12000
51.1k
                case value_t::number_unsigned:
12001
0
                {
12002
0
                    number_unsigned = number_unsigned_t(0);
12003
0
                    break;
12004
51.1k
                }
12005
51.1k
12006
51.1k
                case value_t::number_float:
12007
0
                {
12008
0
                    number_float = number_float_t(0.0);
12009
0
                    break;
12010
51.1k
                }
12011
51.1k
12012
251k
                case value_t::null:
12013
251k
                {
12014
251k
                    object = nullptr;  // silence warning, see #821
12015
251k
                    break;
12016
51.1k
                }
12017
51.1k
12018
51.1k
                default:
12019
0
                {
12020
0
                    object = nullptr;  // silence warning, see #821
12021
0
                    if (JSON_UNLIKELY(t == value_t::null))
12022
0
                    {
12023
0
                        JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.2.0")); // LCOV_EXCL_LINE
12024
0
                    }
12025
0
                    break;
12026
0
                }
12027
302k
            }
12028
302k
        }
12029
12030
        /// constructor for strings
12031
        json_value(const string_t& value)
12032
92.9k
        {
12033
92.9k
            string = create<string_t>(value);
12034
92.9k
        }
Unexecuted instantiation: _ZN8nlohmann10basic_json10json_valueC2ERKT1_
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE10json_valueC2ERKS8_
Line
Count
Source
12032
92.9k
        {
12033
92.9k
            string = create<string_t>(value);
12034
92.9k
        }
12035
12036
        /// constructor for rvalue strings
12037
        json_value(string_t&& value)
12038
423
        {
12039
423
            string = create<string_t>(std::move(value));
12040
423
        }
Unexecuted instantiation: _ZN8nlohmann10basic_json10json_valueC2EOT1_
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE10json_valueC2EOS8_
Line
Count
Source
12038
423
        {
12039
423
            string = create<string_t>(std::move(value));
12040
423
        }
12041
12042
        /// constructor for objects
12043
        json_value(const object_t& value)
12044
5.79k
        {
12045
5.79k
            object = create<object_t>(value);
12046
5.79k
        }
Unexecuted instantiation: _ZN8nlohmann10basic_json10json_valueC2ERKT_IT1_NS_10basic_jsonIS2_T0_S3_T2_T3_T4_T5_T6_T7_EEJSt4lessIvESA_ISt4pairIKS3_SD_EEEE
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE10json_valueC2ERKS1_IS8_SA_St4lessIvESaISt4pairIKS8_SA_EEE
Line
Count
Source
12044
5.79k
        {
12045
5.79k
            object = create<object_t>(value);
12046
5.79k
        }
12047
12048
        /// constructor for rvalue objects
12049
        json_value(object_t&& value)
12050
0
        {
12051
0
            object = create<object_t>(std::move(value));
12052
0
        }
12053
12054
        /// constructor for arrays
12055
        json_value(const array_t& value)
12056
24
        {
12057
24
            array = create<array_t>(value);
12058
24
        }
Unexecuted instantiation: _ZN8nlohmann10basic_json10json_valueC2ERKT0_INS_10basic_jsonIT_S2_T1_T2_T3_T4_T5_T6_T7_EEJSA_ISD_EEE
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE10json_valueC2ERKS2_ISA_SaISA_EE
Line
Count
Source
12056
24
        {
12057
24
            array = create<array_t>(value);
12058
24
        }
12059
12060
        /// constructor for rvalue arrays
12061
        json_value(array_t&& value)
12062
0
        {
12063
0
            array = create<array_t>(std::move(value));
12064
0
        }
12065
12066
        void destroy(value_t t) noexcept
12067
565k
        {
12068
565k
            switch (t)
12069
565k
            {
12070
565k
                case value_t::object:
12071
57.0k
                {
12072
57.0k
                    AllocatorType<object_t> alloc;
12073
57.0k
                    std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
12074
57.0k
                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
12075
57.0k
                    break;
12076
57.0k
                }
12077
57.0k
12078
57.0k
                case value_t::array:
12079
625
                {
12080
625
                    AllocatorType<array_t> alloc;
12081
625
                    std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
12082
625
                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
12083
625
                    break;
12084
57.0k
                }
12085
57.0k
12086
93.5k
                case value_t::string:
12087
93.5k
                {
12088
93.5k
                    AllocatorType<string_t> alloc;
12089
93.5k
                    std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
12090
93.5k
                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
12091
93.5k
                    break;
12092
57.0k
                }
12093
57.0k
12094
414k
                default:
12095
414k
                {
12096
414k
                    break;
12097
57.0k
                }
12098
565k
            }
12099
565k
        }
Unexecuted instantiation: _ZN8nlohmann10basic_json10json_value7destroyENS_6detail7value_tE
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE10json_value7destroyENS_6detail7value_tE
Line
Count
Source
12067
565k
        {
12068
565k
            switch (t)
12069
565k
            {
12070
565k
                case value_t::object:
12071
57.0k
                {
12072
57.0k
                    AllocatorType<object_t> alloc;
12073
57.0k
                    std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
12074
57.0k
                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
12075
57.0k
                    break;
12076
57.0k
                }
12077
57.0k
12078
57.0k
                case value_t::array:
12079
625
                {
12080
625
                    AllocatorType<array_t> alloc;
12081
625
                    std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
12082
625
                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
12083
625
                    break;
12084
57.0k
                }
12085
57.0k
12086
93.5k
                case value_t::string:
12087
93.5k
                {
12088
93.5k
                    AllocatorType<string_t> alloc;
12089
93.5k
                    std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
12090
93.5k
                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
12091
93.5k
                    break;
12092
57.0k
                }
12093
57.0k
12094
414k
                default:
12095
414k
                {
12096
414k
                    break;
12097
57.0k
                }
12098
565k
            }
12099
565k
        }
12100
    };
12101
12102
    /*!
12103
    @brief checks the class invariants
12104
12105
    This function asserts the class invariants. It needs to be called at the
12106
    end of every constructor to make sure that created objects respect the
12107
    invariant. Furthermore, it has to be called each time the type of a JSON
12108
    value is changed, because the invariant expresses a relationship between
12109
    @a m_type and @a m_value.
12110
    */
12111
    void assert_invariant() const noexcept
12112
2.14M
    {
12113
2.14M
        assert(m_type != value_t::object or m_value.object != nullptr);
12114
2.14M
        assert(m_type != value_t::array or m_value.array != nullptr);
12115
2.14M
        assert(m_type != value_t::string or m_value.string != nullptr);
12116
2.14M
    }
12117
12118
  public:
12119
    //////////////////////////
12120
    // JSON parser callback //
12121
    //////////////////////////
12122
12123
    /*!
12124
    @brief parser event types
12125
12126
    The parser callback distinguishes the following events:
12127
    - `object_start`: the parser read `{` and started to process a JSON object
12128
    - `key`: the parser read a key of a value in an object
12129
    - `object_end`: the parser read `}` and finished processing a JSON object
12130
    - `array_start`: the parser read `[` and started to process a JSON array
12131
    - `array_end`: the parser read `]` and finished processing a JSON array
12132
    - `value`: the parser finished reading a JSON value
12133
12134
    @image html callback_events.png "Example when certain parse events are triggered"
12135
12136
    @sa @ref parser_callback_t for more information and examples
12137
    */
12138
    using parse_event_t = typename parser::parse_event_t;
12139
12140
    /*!
12141
    @brief per-element parser callback type
12142
12143
    With a parser callback function, the result of parsing a JSON text can be
12144
    influenced. When passed to @ref parse, it is called on certain events
12145
    (passed as @ref parse_event_t via parameter @a event) with a set recursion
12146
    depth @a depth and context JSON value @a parsed. The return value of the
12147
    callback function is a boolean indicating whether the element that emitted
12148
    the callback shall be kept or not.
12149
12150
    We distinguish six scenarios (determined by the event type) in which the
12151
    callback function can be called. The following table describes the values
12152
    of the parameters @a depth, @a event, and @a parsed.
12153
12154
    parameter @a event | description | parameter @a depth | parameter @a parsed
12155
    ------------------ | ----------- | ------------------ | -------------------
12156
    parse_event_t::object_start | the parser read `{` and started to process a JSON object | depth of the parent of the JSON object | a JSON value with type discarded
12157
    parse_event_t::key | the parser read a key of a value in an object | depth of the currently parsed JSON object | a JSON string containing the key
12158
    parse_event_t::object_end | the parser read `}` and finished processing a JSON object | depth of the parent of the JSON object | the parsed JSON object
12159
    parse_event_t::array_start | the parser read `[` and started to process a JSON array | depth of the parent of the JSON array | a JSON value with type discarded
12160
    parse_event_t::array_end | the parser read `]` and finished processing a JSON array | depth of the parent of the JSON array | the parsed JSON array
12161
    parse_event_t::value | the parser finished reading a JSON value | depth of the value | the parsed JSON value
12162
12163
    @image html callback_events.png "Example when certain parse events are triggered"
12164
12165
    Discarding a value (i.e., returning `false`) has different effects
12166
    depending on the context in which function was called:
12167
12168
    - Discarded values in structured types are skipped. That is, the parser
12169
      will behave as if the discarded value was never read.
12170
    - In case a value outside a structured type is skipped, it is replaced
12171
      with `null`. This case happens if the top-level element is skipped.
12172
12173
    @param[in] depth  the depth of the recursion during parsing
12174
12175
    @param[in] event  an event of type parse_event_t indicating the context in
12176
    the callback function has been called
12177
12178
    @param[in,out] parsed  the current intermediate parse result; note that
12179
    writing to this value has no effect for parse_event_t::key events
12180
12181
    @return Whether the JSON value which called the function during parsing
12182
    should be kept (`true`) or not (`false`). In the latter case, it is either
12183
    skipped completely or replaced by an empty discarded object.
12184
12185
    @sa @ref parse for examples
12186
12187
    @since version 1.0.0
12188
    */
12189
    using parser_callback_t = typename parser::parser_callback_t;
12190
12191
    //////////////////
12192
    // constructors //
12193
    //////////////////
12194
12195
    /// @name constructors and destructors
12196
    /// Constructors of class @ref basic_json, copy/move constructor, copy
12197
    /// assignment, static functions creating objects, and the destructor.
12198
    /// @{
12199
12200
    /*!
12201
    @brief create an empty value with a given type
12202
12203
    Create an empty JSON value with a given type. The value will be default
12204
    initialized with an empty value which depends on the type:
12205
12206
    Value type  | initial value
12207
    ----------- | -------------
12208
    null        | `null`
12209
    boolean     | `false`
12210
    string      | `""`
12211
    number      | `0`
12212
    object      | `{}`
12213
    array       | `[]`
12214
12215
    @param[in] v  the type of the value to create
12216
12217
    @complexity Constant.
12218
12219
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
12220
    changes to any JSON value.
12221
12222
    @liveexample{The following code shows the constructor for different @ref
12223
    value_t values,basic_json__value_t}
12224
12225
    @sa @ref clear() -- restores the postcondition of this constructor
12226
12227
    @since version 1.0.0
12228
    */
12229
    basic_json(const value_t v)
12230
        : m_type(v), m_value(v)
12231
302k
    {
12232
302k
        assert_invariant();
12233
302k
    }
12234
12235
    /*!
12236
    @brief create a null object
12237
12238
    Create a `null` JSON value. It either takes a null pointer as parameter
12239
    (explicitly creating `null`) or no parameter (implicitly creating `null`).
12240
    The passed null pointer itself is not read -- it is only used to choose
12241
    the right constructor.
12242
12243
    @complexity Constant.
12244
12245
    @exceptionsafety No-throw guarantee: this constructor never throws
12246
    exceptions.
12247
12248
    @liveexample{The following code shows the constructor with and without a
12249
    null pointer parameter.,basic_json__nullptr_t}
12250
12251
    @since version 1.0.0
12252
    */
12253
    basic_json(std::nullptr_t = nullptr) noexcept
12254
        : basic_json(value_t::null)
12255
251k
    {
12256
251k
        assert_invariant();
12257
251k
    }
12258
12259
    /*!
12260
    @brief create a JSON value
12261
12262
    This is a "catch all" constructor for all compatible JSON types; that is,
12263
    types for which a `to_json()` method exists. The constructor forwards the
12264
    parameter @a val to that method (to `json_serializer<U>::to_json` method
12265
    with `U = uncvref_t<CompatibleType>`, to be exact).
12266
12267
    Template type @a CompatibleType includes, but is not limited to, the
12268
    following types:
12269
    - **arrays**: @ref array_t and all kinds of compatible containers such as
12270
      `std::vector`, `std::deque`, `std::list`, `std::forward_list`,
12271
      `std::array`, `std::valarray`, `std::set`, `std::unordered_set`,
12272
      `std::multiset`, and `std::unordered_multiset` with a `value_type` from
12273
      which a @ref basic_json value can be constructed.
12274
    - **objects**: @ref object_t and all kinds of compatible associative
12275
      containers such as `std::map`, `std::unordered_map`, `std::multimap`,
12276
      and `std::unordered_multimap` with a `key_type` compatible to
12277
      @ref string_t and a `value_type` from which a @ref basic_json value can
12278
      be constructed.
12279
    - **strings**: @ref string_t, string literals, and all compatible string
12280
      containers can be used.
12281
    - **numbers**: @ref number_integer_t, @ref number_unsigned_t,
12282
      @ref number_float_t, and all convertible number types such as `int`,
12283
      `size_t`, `int64_t`, `float` or `double` can be used.
12284
    - **boolean**: @ref boolean_t / `bool` can be used.
12285
12286
    See the examples below.
12287
12288
    @tparam CompatibleType a type such that:
12289
    - @a CompatibleType is not derived from `std::istream`,
12290
    - @a CompatibleType is not @ref basic_json (to avoid hijacking copy/move
12291
         constructors),
12292
    - @a CompatibleType is not a different @ref basic_json type (i.e. with different template arguments)
12293
    - @a CompatibleType is not a @ref basic_json nested type (e.g.,
12294
         @ref json_pointer, @ref iterator, etc ...)
12295
    - @ref @ref json_serializer<U> has a
12296
         `to_json(basic_json_t&, CompatibleType&&)` method
12297
12298
    @tparam U = `uncvref_t<CompatibleType>`
12299
12300
    @param[in] val the value to be forwarded to the respective constructor
12301
12302
    @complexity Usually linear in the size of the passed @a val, also
12303
                depending on the implementation of the called `to_json()`
12304
                method.
12305
12306
    @exceptionsafety Depends on the called constructor. For types directly
12307
    supported by the library (i.e., all types for which no `to_json()` function
12308
    was provided), strong guarantee holds: if an exception is thrown, there are
12309
    no changes to any JSON value.
12310
12311
    @liveexample{The following code shows the constructor with several
12312
    compatible types.,basic_json__CompatibleType}
12313
12314
    @since version 2.1.0
12315
    */
12316
    template <typename CompatibleType,
12317
              typename U = detail::uncvref_t<CompatibleType>,
12318
              detail::enable_if_t<
12319
                  not detail::is_basic_json<U>::value and detail::is_compatible_type<basic_json_t, U>::value, int> = 0>
12320
    basic_json(CompatibleType && val) noexcept(noexcept(
12321
                JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
12322
                                           std::forward<CompatibleType>(val))))
12323
207k
    {
12324
207k
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
12325
207k
        assert_invariant();
12326
207k
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEC2IRS8_S8_Li0EEEOT_
Line
Count
Source
12323
62.5k
    {
12324
62.5k
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
12325
62.5k
        assert_invariant();
12326
62.5k
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEC2IRddLi0EEEOT_
Line
Count
Source
12323
57.4k
    {
12324
57.4k
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
12325
57.4k
        assert_invariant();
12326
57.4k
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEC2IRbbLi0EEEOT_
Line
Count
Source
12323
602
    {
12324
602
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
12325
602
        assert_invariant();
12326
602
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEC2IRllLi0EEEOT_
Line
Count
Source
12323
9.18k
    {
12324
9.18k
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
12325
9.18k
        assert_invariant();
12326
9.18k
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEC2IRmmLi0EEEOT_
Line
Count
Source
12323
77.0k
    {
12324
77.0k
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
12325
77.0k
        assert_invariant();
12326
77.0k
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEC2IRA474_KcA474_cLi0EEEOT_
Line
Count
Source
12323
199
    {
12324
199
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
12325
199
        assert_invariant();
12326
199
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEC2IS8_S8_Li0EEEOT_
Line
Count
Source
12323
423
    {
12324
423
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
12325
423
        assert_invariant();
12326
423
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEC2IKS8_S8_Li0EEEOT_
Line
Count
Source
12323
47
    {
12324
47
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
12325
47
        assert_invariant();
12326
47
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEC2IRjjLi0EEEOT_
Line
Count
Source
12323
141
    {
12324
141
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
12325
141
        assert_invariant();
12326
141
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEC2IRKPKcSD_Li0EEEOT_
Line
Count
Source
12323
10
    {
12324
10
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
12325
10
        assert_invariant();
12326
10
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEC2IbbLi0EEEOT_
Line
Count
Source
12323
1
    {
12324
1
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
12325
1
        assert_invariant();
12326
1
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEC2IddLi0EEEOT_
Line
Count
Source
12323
1
    {
12324
1
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
12325
1
        assert_invariant();
12326
1
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEC2IRA6_KcA6_cLi0EEEOT_
Line
Count
Source
12323
1
    {
12324
1
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
12325
1
        assert_invariant();
12326
1
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEC2IiiLi0EEEOT_
Line
Count
Source
12323
1
    {
12324
1
        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
12325
1
        assert_invariant();
12326
1
    }
12327
12328
    /*!
12329
    @brief create a JSON value from an existing one
12330
12331
    This is a constructor for existing @ref basic_json types.
12332
    It does not hijack copy/move constructors, since the parameter has different
12333
    template arguments than the current ones.
12334
12335
    The constructor tries to convert the internal @ref m_value of the parameter.
12336
12337
    @tparam BasicJsonType a type such that:
12338
    - @a BasicJsonType is a @ref basic_json type.
12339
    - @a BasicJsonType has different template arguments than @ref basic_json_t.
12340
12341
    @param[in] val the @ref basic_json value to be converted.
12342
12343
    @complexity Usually linear in the size of the passed @a val, also
12344
                depending on the implementation of the called `to_json()`
12345
                method.
12346
12347
    @exceptionsafety Depends on the called constructor. For types directly
12348
    supported by the library (i.e., all types for which no `to_json()` function
12349
    was provided), strong guarantee holds: if an exception is thrown, there are
12350
    no changes to any JSON value.
12351
12352
    @since version 3.2.0
12353
    */
12354
    template <typename BasicJsonType,
12355
              detail::enable_if_t<
12356
                  detail::is_basic_json<BasicJsonType>::value and not std::is_same<basic_json, BasicJsonType>::value, int> = 0>
12357
    basic_json(const BasicJsonType& val)
12358
    {
12359
        using other_boolean_t = typename BasicJsonType::boolean_t;
12360
        using other_number_float_t = typename BasicJsonType::number_float_t;
12361
        using other_number_integer_t = typename BasicJsonType::number_integer_t;
12362
        using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
12363
        using other_string_t = typename BasicJsonType::string_t;
12364
        using other_object_t = typename BasicJsonType::object_t;
12365
        using other_array_t = typename BasicJsonType::array_t;
12366
12367
        switch (val.type())
12368
        {
12369
            case value_t::boolean:
12370
                JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
12371
                break;
12372
            case value_t::number_float:
12373
                JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
12374
                break;
12375
            case value_t::number_integer:
12376
                JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
12377
                break;
12378
            case value_t::number_unsigned:
12379
                JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
12380
                break;
12381
            case value_t::string:
12382
                JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
12383
                break;
12384
            case value_t::object:
12385
                JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
12386
                break;
12387
            case value_t::array:
12388
                JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
12389
                break;
12390
            case value_t::null:
12391
                *this = nullptr;
12392
                break;
12393
            case value_t::discarded:
12394
                m_type = value_t::discarded;
12395
                break;
12396
        }
12397
        assert_invariant();
12398
    }
12399
12400
    /*!
12401
    @brief create a container (array or object) from an initializer list
12402
12403
    Creates a JSON value of type array or object from the passed initializer
12404
    list @a init. In case @a type_deduction is `true` (default), the type of
12405
    the JSON value to be created is deducted from the initializer list @a init
12406
    according to the following rules:
12407
12408
    1. If the list is empty, an empty JSON object value `{}` is created.
12409
    2. If the list consists of pairs whose first element is a string, a JSON
12410
       object value is created where the first elements of the pairs are
12411
       treated as keys and the second elements are as values.
12412
    3. In all other cases, an array is created.
12413
12414
    The rules aim to create the best fit between a C++ initializer list and
12415
    JSON values. The rationale is as follows:
12416
12417
    1. The empty initializer list is written as `{}` which is exactly an empty
12418
       JSON object.
12419
    2. C++ has no way of describing mapped types other than to list a list of
12420
       pairs. As JSON requires that keys must be of type string, rule 2 is the
12421
       weakest constraint one can pose on initializer lists to interpret them
12422
       as an object.
12423
    3. In all other cases, the initializer list could not be interpreted as
12424
       JSON object type, so interpreting it as JSON array type is safe.
12425
12426
    With the rules described above, the following JSON values cannot be
12427
    expressed by an initializer list:
12428
12429
    - the empty array (`[]`): use @ref array(initializer_list_t)
12430
      with an empty initializer list in this case
12431
    - arrays whose elements satisfy rule 2: use @ref
12432
      array(initializer_list_t) with the same initializer list
12433
      in this case
12434
12435
    @note When used without parentheses around an empty initializer list, @ref
12436
    basic_json() is called instead of this function, yielding the JSON null
12437
    value.
12438
12439
    @param[in] init  initializer list with JSON values
12440
12441
    @param[in] type_deduction internal parameter; when set to `true`, the type
12442
    of the JSON value is deducted from the initializer list @a init; when set
12443
    to `false`, the type provided via @a manual_type is forced. This mode is
12444
    used by the functions @ref array(initializer_list_t) and
12445
    @ref object(initializer_list_t).
12446
12447
    @param[in] manual_type internal parameter; when @a type_deduction is set
12448
    to `false`, the created JSON value will use the provided type (only @ref
12449
    value_t::array and @ref value_t::object are valid); when @a type_deduction
12450
    is set to `true`, this parameter has no effect
12451
12452
    @throw type_error.301 if @a type_deduction is `false`, @a manual_type is
12453
    `value_t::object`, but @a init contains an element which is not a pair
12454
    whose first element is a string. In this case, the constructor could not
12455
    create an object. If @a type_deduction would have be `true`, an array
12456
    would have been created. See @ref object(initializer_list_t)
12457
    for an example.
12458
12459
    @complexity Linear in the size of the initializer list @a init.
12460
12461
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
12462
    changes to any JSON value.
12463
12464
    @liveexample{The example below shows how JSON values are created from
12465
    initializer lists.,basic_json__list_init_t}
12466
12467
    @sa @ref array(initializer_list_t) -- create a JSON array
12468
    value from an initializer list
12469
    @sa @ref object(initializer_list_t) -- create a JSON object
12470
    value from an initializer list
12471
12472
    @since version 1.0.0
12473
    */
12474
    basic_json(initializer_list_t init,
12475
               bool type_deduction = true,
12476
               value_t manual_type = value_t::array)
12477
    {
12478
        // check if each element is an array with two elements whose first
12479
        // element is a string
12480
        bool is_an_object = std::all_of(init.begin(), init.end(),
12481
                                        [](const detail::json_ref<basic_json>& element_ref)
12482
        {
12483
            return (element_ref->is_array() and element_ref->size() == 2 and (*element_ref)[0].is_string());
12484
        });
12485
12486
        // adjust type if type deduction is not wanted
12487
        if (not type_deduction)
12488
        {
12489
            // if array is wanted, do not create an object though possible
12490
            if (manual_type == value_t::array)
12491
            {
12492
                is_an_object = false;
12493
            }
12494
12495
            // if object is wanted but impossible, throw an exception
12496
            if (JSON_UNLIKELY(manual_type == value_t::object and not is_an_object))
12497
            {
12498
                JSON_THROW(type_error::create(301, "cannot create object from initializer list"));
12499
            }
12500
        }
12501
12502
        if (is_an_object)
12503
        {
12504
            // the initializer list is a list of pairs -> create object
12505
            m_type = value_t::object;
12506
            m_value = value_t::object;
12507
12508
            std::for_each(init.begin(), init.end(), [this](const detail::json_ref<basic_json>& element_ref)
12509
            {
12510
                auto element = element_ref.moved_or_copied();
12511
                m_value.object->emplace(
12512
                    std::move(*((*element.m_value.array)[0].m_value.string)),
12513
                    std::move((*element.m_value.array)[1]));
12514
            });
12515
        }
12516
        else
12517
        {
12518
            // the initializer list describes an array -> create array
12519
            m_type = value_t::array;
12520
            m_value.array = create<array_t>(init.begin(), init.end());
12521
        }
12522
12523
        assert_invariant();
12524
    }
12525
12526
    /*!
12527
    @brief explicitly create an array from an initializer list
12528
12529
    Creates a JSON array value from a given initializer list. That is, given a
12530
    list of values `a, b, c`, creates the JSON value `[a, b, c]`. If the
12531
    initializer list is empty, the empty array `[]` is created.
12532
12533
    @note This function is only needed to express two edge cases that cannot
12534
    be realized with the initializer list constructor (@ref
12535
    basic_json(initializer_list_t, bool, value_t)). These cases
12536
    are:
12537
    1. creating an array whose elements are all pairs whose first element is a
12538
    string -- in this case, the initializer list constructor would create an
12539
    object, taking the first elements as keys
12540
    2. creating an empty array -- passing the empty initializer list to the
12541
    initializer list constructor yields an empty object
12542
12543
    @param[in] init  initializer list with JSON values to create an array from
12544
    (optional)
12545
12546
    @return JSON array value
12547
12548
    @complexity Linear in the size of @a init.
12549
12550
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
12551
    changes to any JSON value.
12552
12553
    @liveexample{The following code shows an example for the `array`
12554
    function.,array}
12555
12556
    @sa @ref basic_json(initializer_list_t, bool, value_t) --
12557
    create a JSON value from an initializer list
12558
    @sa @ref object(initializer_list_t) -- create a JSON object
12559
    value from an initializer list
12560
12561
    @since version 1.0.0
12562
    */
12563
    static basic_json array(initializer_list_t init = {})
12564
    {
12565
        return basic_json(init, false, value_t::array);
12566
    }
12567
12568
    /*!
12569
    @brief explicitly create an object from an initializer list
12570
12571
    Creates a JSON object value from a given initializer list. The initializer
12572
    lists elements must be pairs, and their first elements must be strings. If
12573
    the initializer list is empty, the empty object `{}` is created.
12574
12575
    @note This function is only added for symmetry reasons. In contrast to the
12576
    related function @ref array(initializer_list_t), there are
12577
    no cases which can only be expressed by this function. That is, any
12578
    initializer list @a init can also be passed to the initializer list
12579
    constructor @ref basic_json(initializer_list_t, bool, value_t).
12580
12581
    @param[in] init  initializer list to create an object from (optional)
12582
12583
    @return JSON object value
12584
12585
    @throw type_error.301 if @a init is not a list of pairs whose first
12586
    elements are strings. In this case, no object can be created. When such a
12587
    value is passed to @ref basic_json(initializer_list_t, bool, value_t),
12588
    an array would have been created from the passed initializer list @a init.
12589
    See example below.
12590
12591
    @complexity Linear in the size of @a init.
12592
12593
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
12594
    changes to any JSON value.
12595
12596
    @liveexample{The following code shows an example for the `object`
12597
    function.,object}
12598
12599
    @sa @ref basic_json(initializer_list_t, bool, value_t) --
12600
    create a JSON value from an initializer list
12601
    @sa @ref array(initializer_list_t) -- create a JSON array
12602
    value from an initializer list
12603
12604
    @since version 1.0.0
12605
    */
12606
    static basic_json object(initializer_list_t init = {})
12607
    {
12608
        return basic_json(init, false, value_t::object);
12609
    }
12610
12611
    /*!
12612
    @brief construct an array with count copies of given value
12613
12614
    Constructs a JSON array value by creating @a cnt copies of a passed value.
12615
    In case @a cnt is `0`, an empty array is created.
12616
12617
    @param[in] cnt  the number of JSON copies of @a val to create
12618
    @param[in] val  the JSON value to copy
12619
12620
    @post `std::distance(begin(),end()) == cnt` holds.
12621
12622
    @complexity Linear in @a cnt.
12623
12624
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
12625
    changes to any JSON value.
12626
12627
    @liveexample{The following code shows examples for the @ref
12628
    basic_json(size_type\, const basic_json&)
12629
    constructor.,basic_json__size_type_basic_json}
12630
12631
    @since version 1.0.0
12632
    */
12633
    basic_json(size_type cnt, const basic_json& val)
12634
        : m_type(value_t::array)
12635
    {
12636
        m_value.array = create<array_t>(cnt, val);
12637
        assert_invariant();
12638
    }
12639
12640
    /*!
12641
    @brief construct a JSON container given an iterator range
12642
12643
    Constructs the JSON value with the contents of the range `[first, last)`.
12644
    The semantics depends on the different types a JSON value can have:
12645
    - In case of a null type, invalid_iterator.206 is thrown.
12646
    - In case of other primitive types (number, boolean, or string), @a first
12647
      must be `begin()` and @a last must be `end()`. In this case, the value is
12648
      copied. Otherwise, invalid_iterator.204 is thrown.
12649
    - In case of structured types (array, object), the constructor behaves as
12650
      similar versions for `std::vector` or `std::map`; that is, a JSON array
12651
      or object is constructed from the values in the range.
12652
12653
    @tparam InputIT an input iterator type (@ref iterator or @ref
12654
    const_iterator)
12655
12656
    @param[in] first begin of the range to copy from (included)
12657
    @param[in] last end of the range to copy from (excluded)
12658
12659
    @pre Iterators @a first and @a last must be initialized. **This
12660
         precondition is enforced with an assertion (see warning).** If
12661
         assertions are switched off, a violation of this precondition yields
12662
         undefined behavior.
12663
12664
    @pre Range `[first, last)` is valid. Usually, this precondition cannot be
12665
         checked efficiently. Only certain edge cases are detected; see the
12666
         description of the exceptions below. A violation of this precondition
12667
         yields undefined behavior.
12668
12669
    @warning A precondition is enforced with a runtime assertion that will
12670
             result in calling `std::abort` if this precondition is not met.
12671
             Assertions can be disabled by defining `NDEBUG` at compile time.
12672
             See https://en.cppreference.com/w/cpp/error/assert for more
12673
             information.
12674
12675
    @throw invalid_iterator.201 if iterators @a first and @a last are not
12676
    compatible (i.e., do not belong to the same JSON value). In this case,
12677
    the range `[first, last)` is undefined.
12678
    @throw invalid_iterator.204 if iterators @a first and @a last belong to a
12679
    primitive type (number, boolean, or string), but @a first does not point
12680
    to the first element any more. In this case, the range `[first, last)` is
12681
    undefined. See example code below.
12682
    @throw invalid_iterator.206 if iterators @a first and @a last belong to a
12683
    null value. In this case, the range `[first, last)` is undefined.
12684
12685
    @complexity Linear in distance between @a first and @a last.
12686
12687
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
12688
    changes to any JSON value.
12689
12690
    @liveexample{The example below shows several ways to create JSON values by
12691
    specifying a subrange with iterators.,basic_json__InputIt_InputIt}
12692
12693
    @since version 1.0.0
12694
    */
12695
    template<class InputIT, typename std::enable_if<
12696
                 std::is_same<InputIT, typename basic_json_t::iterator>::value or
12697
                 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int>::type = 0>
12698
    basic_json(InputIT first, InputIT last)
12699
    {
12700
        assert(first.m_object != nullptr);
12701
        assert(last.m_object != nullptr);
12702
12703
        // make sure iterator fits the current value
12704
        if (JSON_UNLIKELY(first.m_object != last.m_object))
12705
        {
12706
            JSON_THROW(invalid_iterator::create(201, "iterators are not compatible"));
12707
        }
12708
12709
        // copy type from first iterator
12710
        m_type = first.m_object->m_type;
12711
12712
        // check if iterator range is complete for primitive values
12713
        switch (m_type)
12714
        {
12715
            case value_t::boolean:
12716
            case value_t::number_float:
12717
            case value_t::number_integer:
12718
            case value_t::number_unsigned:
12719
            case value_t::string:
12720
            {
12721
                if (JSON_UNLIKELY(not first.m_it.primitive_iterator.is_begin()
12722
                                  or not last.m_it.primitive_iterator.is_end()))
12723
                {
12724
                    JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
12725
                }
12726
                break;
12727
            }
12728
12729
            default:
12730
                break;
12731
        }
12732
12733
        switch (m_type)
12734
        {
12735
            case value_t::number_integer:
12736
            {
12737
                m_value.number_integer = first.m_object->m_value.number_integer;
12738
                break;
12739
            }
12740
12741
            case value_t::number_unsigned:
12742
            {
12743
                m_value.number_unsigned = first.m_object->m_value.number_unsigned;
12744
                break;
12745
            }
12746
12747
            case value_t::number_float:
12748
            {
12749
                m_value.number_float = first.m_object->m_value.number_float;
12750
                break;
12751
            }
12752
12753
            case value_t::boolean:
12754
            {
12755
                m_value.boolean = first.m_object->m_value.boolean;
12756
                break;
12757
            }
12758
12759
            case value_t::string:
12760
            {
12761
                m_value = *first.m_object->m_value.string;
12762
                break;
12763
            }
12764
12765
            case value_t::object:
12766
            {
12767
                m_value.object = create<object_t>(first.m_it.object_iterator,
12768
                                                  last.m_it.object_iterator);
12769
                break;
12770
            }
12771
12772
            case value_t::array:
12773
            {
12774
                m_value.array = create<array_t>(first.m_it.array_iterator,
12775
                                                last.m_it.array_iterator);
12776
                break;
12777
            }
12778
12779
            default:
12780
                JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " +
12781
                                                    std::string(first.m_object->type_name())));
12782
        }
12783
12784
        assert_invariant();
12785
    }
12786
12787
12788
    ///////////////////////////////////////
12789
    // other constructors and destructor //
12790
    ///////////////////////////////////////
12791
12792
    /// @private
12793
    basic_json(const detail::json_ref<basic_json>& ref)
12794
        : basic_json(ref.moved_or_copied())
12795
    {}
12796
12797
    /*!
12798
    @brief copy constructor
12799
12800
    Creates a copy of a given JSON value.
12801
12802
    @param[in] other  the JSON value to copy
12803
12804
    @post `*this == other`
12805
12806
    @complexity Linear in the size of @a other.
12807
12808
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
12809
    changes to any JSON value.
12810
12811
    @requirement This function helps `basic_json` satisfying the
12812
    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
12813
    requirements:
12814
    - The complexity is linear.
12815
    - As postcondition, it holds: `other == basic_json(other)`.
12816
12817
    @liveexample{The following code shows an example for the copy
12818
    constructor.,basic_json__basic_json}
12819
12820
    @since version 1.0.0
12821
    */
12822
    basic_json(const basic_json& other)
12823
        : m_type(other.m_type)
12824
42.8k
    {
12825
42.8k
        // check of passed value is valid
12826
42.8k
        other.assert_invariant();
12827
42.8k
12828
42.8k
        switch (m_type)
12829
42.8k
        {
12830
42.8k
            case value_t::object:
12831
5.79k
            {
12832
5.79k
                m_value = *other.m_value.object;
12833
5.79k
                break;
12834
5.79k
            }
12835
5.79k
12836
5.79k
            case value_t::array:
12837
24
            {
12838
24
                m_value = *other.m_value.array;
12839
24
                break;
12840
5.79k
            }
12841
5.79k
12842
30.3k
            case value_t::string:
12843
30.3k
            {
12844
30.3k
                m_value = *other.m_value.string;
12845
30.3k
                break;
12846
5.79k
            }
12847
5.79k
12848
5.79k
            case value_t::boolean:
12849
12
            {
12850
12
                m_value = other.m_value.boolean;
12851
12
                break;
12852
5.79k
            }
12853
5.79k
12854
5.79k
            case value_t::number_integer:
12855
421
            {
12856
421
                m_value = other.m_value.number_integer;
12857
421
                break;
12858
5.79k
            }
12859
5.79k
12860
5.79k
            case value_t::number_unsigned:
12861
3.66k
            {
12862
3.66k
                m_value = other.m_value.number_unsigned;
12863
3.66k
                break;
12864
5.79k
            }
12865
5.79k
12866
5.79k
            case value_t::number_float:
12867
2.62k
            {
12868
2.62k
                m_value = other.m_value.number_float;
12869
2.62k
                break;
12870
5.79k
            }
12871
5.79k
12872
5.79k
            default:
12873
8
                break;
12874
42.8k
        }
12875
42.8k
12876
42.8k
        assert_invariant();
12877
42.8k
    }
12878
12879
    /*!
12880
    @brief move constructor
12881
12882
    Move constructor. Constructs a JSON value with the contents of the given
12883
    value @a other using move semantics. It "steals" the resources from @a
12884
    other and leaves it as JSON null value.
12885
12886
    @param[in,out] other  value to move to this object
12887
12888
    @post `*this` has the same value as @a other before the call.
12889
    @post @a other is a JSON null value.
12890
12891
    @complexity Constant.
12892
12893
    @exceptionsafety No-throw guarantee: this constructor never throws
12894
    exceptions.
12895
12896
    @requirement This function helps `basic_json` satisfying the
12897
    [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible)
12898
    requirements.
12899
12900
    @liveexample{The code below shows the move constructor explicitly called
12901
    via std::move.,basic_json__moveconstructor}
12902
12903
    @since version 1.0.0
12904
    */
12905
    basic_json(basic_json&& other) noexcept
12906
        : m_type(std::move(other.m_type)),
12907
          m_value(std::move(other.m_value))
12908
12.3k
    {
12909
12.3k
        // check that passed value is valid
12910
12.3k
        other.assert_invariant();
12911
12.3k
12912
12.3k
        // invalidate payload
12913
12.3k
        other.m_type = value_t::null;
12914
12.3k
        other.m_value = {};
12915
12.3k
12916
12.3k
        assert_invariant();
12917
12.3k
    }
12918
12919
    /*!
12920
    @brief copy assignment
12921
12922
    Copy assignment operator. Copies a JSON value via the "copy and swap"
12923
    strategy: It is expressed in terms of the copy constructor, destructor,
12924
    and the `swap()` member function.
12925
12926
    @param[in] other  value to copy from
12927
12928
    @complexity Linear.
12929
12930
    @requirement This function helps `basic_json` satisfying the
12931
    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
12932
    requirements:
12933
    - The complexity is linear.
12934
12935
    @liveexample{The code below shows and example for the copy assignment. It
12936
    creates a copy of value `a` which is then swapped with `b`. Finally\, the
12937
    copy of `a` (which is the null value after the swap) is
12938
    destroyed.,basic_json__copyassignment}
12939
12940
    @since version 1.0.0
12941
    */
12942
    reference& operator=(basic_json other) noexcept (
12943
        std::is_nothrow_move_constructible<value_t>::value and
12944
        std::is_nothrow_move_assignable<value_t>::value and
12945
        std::is_nothrow_move_constructible<json_value>::value and
12946
        std::is_nothrow_move_assignable<json_value>::value
12947
    )
12948
250k
    {
12949
250k
        // check that passed value is valid
12950
250k
        other.assert_invariant();
12951
250k
12952
250k
        using std::swap;
12953
250k
        swap(m_type, other.m_type);
12954
250k
        swap(m_value, other.m_value);
12955
250k
12956
250k
        assert_invariant();
12957
250k
        return *this;
12958
250k
    }
12959
12960
    /*!
12961
    @brief destructor
12962
12963
    Destroys the JSON value and frees all allocated memory.
12964
12965
    @complexity Linear.
12966
12967
    @requirement This function helps `basic_json` satisfying the
12968
    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
12969
    requirements:
12970
    - The complexity is linear.
12971
    - All stored elements are destroyed and all memory is freed.
12972
12973
    @since version 1.0.0
12974
    */
12975
    ~basic_json() noexcept
12976
565k
    {
12977
565k
        assert_invariant();
12978
565k
        m_value.destroy(m_type);
12979
565k
    }
12980
12981
    /// @}
12982
12983
  public:
12984
    ///////////////////////
12985
    // object inspection //
12986
    ///////////////////////
12987
12988
    /// @name object inspection
12989
    /// Functions to inspect the type of a JSON value.
12990
    /// @{
12991
12992
    /*!
12993
    @brief serialization
12994
12995
    Serialization function for JSON values. The function tries to mimic
12996
    Python's `json.dumps()` function, and currently supports its @a indent
12997
    and @a ensure_ascii parameters.
12998
12999
    @param[in] indent If indent is nonnegative, then array elements and object
13000
    members will be pretty-printed with that indent level. An indent level of
13001
    `0` will only insert newlines. `-1` (the default) selects the most compact
13002
    representation.
13003
    @param[in] indent_char The character to use for indentation if @a indent is
13004
    greater than `0`. The default is ` ` (space).
13005
    @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters
13006
    in the output are escaped with `\uXXXX` sequences, and the result consists
13007
    of ASCII characters only.
13008
13009
    @return string containing the serialization of the JSON value
13010
13011
    @throw type_error.316 if a string stored inside the JSON value is not
13012
                          UTF-8 encoded
13013
13014
    @complexity Linear.
13015
13016
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
13017
    changes in the JSON value.
13018
13019
    @liveexample{The following example shows the effect of different @a indent\,
13020
    @a indent_char\, and @a ensure_ascii parameters to the result of the
13021
    serialization.,dump}
13022
13023
    @see https://docs.python.org/2/library/json.html#json.dump
13024
13025
    @since version 1.0.0; indentation character @a indent_char, option
13026
           @a ensure_ascii and exceptions added in version 3.0.0
13027
    */
13028
    string_t dump(const int indent = -1, const char indent_char = ' ',
13029
                  const bool ensure_ascii = false) const
13030
17
    {
13031
17
        string_t result;
13032
17
        serializer s(detail::output_adapter<char, string_t>(result), indent_char);
13033
17
13034
17
        if (indent >= 0)
13035
17
        {
13036
15
            s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
13037
15
        }
13038
17
        else
13039
17
        {
13040
2
            s.dump(*this, false, ensure_ascii, 0);
13041
2
        }
13042
17
13043
17
        return result;
13044
17
    }
13045
13046
    /*!
13047
    @brief return the type of the JSON value (explicit)
13048
13049
    Return the type of the JSON value as a value from the @ref value_t
13050
    enumeration.
13051
13052
    @return the type of the JSON value
13053
            Value type                | return value
13054
            ------------------------- | -------------------------
13055
            null                      | value_t::null
13056
            boolean                   | value_t::boolean
13057
            string                    | value_t::string
13058
            number (integer)          | value_t::number_integer
13059
            number (unsigned integer) | value_t::number_unsigned
13060
            number (floating-point)   | value_t::number_float
13061
            object                    | value_t::object
13062
            array                     | value_t::array
13063
            discarded                 | value_t::discarded
13064
13065
    @complexity Constant.
13066
13067
    @exceptionsafety No-throw guarantee: this member function never throws
13068
    exceptions.
13069
13070
    @liveexample{The following code exemplifies `type()` for all JSON
13071
    types.,type}
13072
13073
    @sa @ref operator value_t() -- return the type of the JSON value (implicit)
13074
    @sa @ref type_name() -- return the type as string
13075
13076
    @since version 1.0.0
13077
    */
13078
    constexpr value_t type() const noexcept
13079
20
    {
13080
20
        return m_type;
13081
20
    }
13082
13083
    /*!
13084
    @brief return whether type is primitive
13085
13086
    This function returns true if and only if the JSON type is primitive
13087
    (string, number, boolean, or null).
13088
13089
    @return `true` if type is primitive (string, number, boolean, or null),
13090
    `false` otherwise.
13091
13092
    @complexity Constant.
13093
13094
    @exceptionsafety No-throw guarantee: this member function never throws
13095
    exceptions.
13096
13097
    @liveexample{The following code exemplifies `is_primitive()` for all JSON
13098
    types.,is_primitive}
13099
13100
    @sa @ref is_structured() -- returns whether JSON value is structured
13101
    @sa @ref is_null() -- returns whether JSON value is `null`
13102
    @sa @ref is_string() -- returns whether JSON value is a string
13103
    @sa @ref is_boolean() -- returns whether JSON value is a boolean
13104
    @sa @ref is_number() -- returns whether JSON value is a number
13105
13106
    @since version 1.0.0
13107
    */
13108
    constexpr bool is_primitive() const noexcept
13109
    {
13110
        return is_null() or is_string() or is_boolean() or is_number();
13111
    }
13112
13113
    /*!
13114
    @brief return whether type is structured
13115
13116
    This function returns true if and only if the JSON type is structured
13117
    (array or object).
13118
13119
    @return `true` if type is structured (array or object), `false` otherwise.
13120
13121
    @complexity Constant.
13122
13123
    @exceptionsafety No-throw guarantee: this member function never throws
13124
    exceptions.
13125
13126
    @liveexample{The following code exemplifies `is_structured()` for all JSON
13127
    types.,is_structured}
13128
13129
    @sa @ref is_primitive() -- returns whether value is primitive
13130
    @sa @ref is_array() -- returns whether value is an array
13131
    @sa @ref is_object() -- returns whether value is an object
13132
13133
    @since version 1.0.0
13134
    */
13135
    constexpr bool is_structured() const noexcept
13136
    {
13137
        return is_array() or is_object();
13138
    }
13139
13140
    /*!
13141
    @brief return whether value is null
13142
13143
    This function returns true if and only if the JSON value is null.
13144
13145
    @return `true` if type is null, `false` otherwise.
13146
13147
    @complexity Constant.
13148
13149
    @exceptionsafety No-throw guarantee: this member function never throws
13150
    exceptions.
13151
13152
    @liveexample{The following code exemplifies `is_null()` for all JSON
13153
    types.,is_null}
13154
13155
    @since version 1.0.0
13156
    */
13157
    constexpr bool is_null() const noexcept
13158
1.62k
    {
13159
1.62k
        return (m_type == value_t::null);
13160
1.62k
    }
13161
13162
    /*!
13163
    @brief return whether value is a boolean
13164
13165
    This function returns true if and only if the JSON value is a boolean.
13166
13167
    @return `true` if type is boolean, `false` otherwise.
13168
13169
    @complexity Constant.
13170
13171
    @exceptionsafety No-throw guarantee: this member function never throws
13172
    exceptions.
13173
13174
    @liveexample{The following code exemplifies `is_boolean()` for all JSON
13175
    types.,is_boolean}
13176
13177
    @since version 1.0.0
13178
    */
13179
    constexpr bool is_boolean() const noexcept
13180
4
    {
13181
4
        return (m_type == value_t::boolean);
13182
4
    }
13183
13184
    /*!
13185
    @brief return whether value is a number
13186
13187
    This function returns true if and only if the JSON value is a number. This
13188
    includes both integer (signed and unsigned) and floating-point values.
13189
13190
    @return `true` if type is number (regardless whether integer, unsigned
13191
    integer or floating-type), `false` otherwise.
13192
13193
    @complexity Constant.
13194
13195
    @exceptionsafety No-throw guarantee: this member function never throws
13196
    exceptions.
13197
13198
    @liveexample{The following code exemplifies `is_number()` for all JSON
13199
    types.,is_number}
13200
13201
    @sa @ref is_number_integer() -- check if value is an integer or unsigned
13202
    integer number
13203
    @sa @ref is_number_unsigned() -- check if value is an unsigned integer
13204
    number
13205
    @sa @ref is_number_float() -- check if value is a floating-point number
13206
13207
    @since version 1.0.0
13208
    */
13209
    constexpr bool is_number() const noexcept
13210
    {
13211
        return is_number_integer() or is_number_float();
13212
    }
13213
13214
    /*!
13215
    @brief return whether value is an integer number
13216
13217
    This function returns true if and only if the JSON value is a signed or
13218
    unsigned integer number. This excludes floating-point values.
13219
13220
    @return `true` if type is an integer or unsigned integer number, `false`
13221
    otherwise.
13222
13223
    @complexity Constant.
13224
13225
    @exceptionsafety No-throw guarantee: this member function never throws
13226
    exceptions.
13227
13228
    @liveexample{The following code exemplifies `is_number_integer()` for all
13229
    JSON types.,is_number_integer}
13230
13231
    @sa @ref is_number() -- check if value is a number
13232
    @sa @ref is_number_unsigned() -- check if value is an unsigned integer
13233
    number
13234
    @sa @ref is_number_float() -- check if value is a floating-point number
13235
13236
    @since version 1.0.0
13237
    */
13238
    constexpr bool is_number_integer() const noexcept
13239
0
    {
13240
0
        return (m_type == value_t::number_integer or m_type == value_t::number_unsigned);
13241
0
    }
13242
13243
    /*!
13244
    @brief return whether value is an unsigned integer number
13245
13246
    This function returns true if and only if the JSON value is an unsigned
13247
    integer number. This excludes floating-point and signed integer values.
13248
13249
    @return `true` if type is an unsigned integer number, `false` otherwise.
13250
13251
    @complexity Constant.
13252
13253
    @exceptionsafety No-throw guarantee: this member function never throws
13254
    exceptions.
13255
13256
    @liveexample{The following code exemplifies `is_number_unsigned()` for all
13257
    JSON types.,is_number_unsigned}
13258
13259
    @sa @ref is_number() -- check if value is a number
13260
    @sa @ref is_number_integer() -- check if value is an integer or unsigned
13261
    integer number
13262
    @sa @ref is_number_float() -- check if value is a floating-point number
13263
13264
    @since version 2.0.0
13265
    */
13266
    constexpr bool is_number_unsigned() const noexcept
13267
152
    {
13268
152
        return (m_type == value_t::number_unsigned);
13269
152
    }
13270
13271
    /*!
13272
    @brief return whether value is a floating-point number
13273
13274
    This function returns true if and only if the JSON value is a
13275
    floating-point number. This excludes signed and unsigned integer values.
13276
13277
    @return `true` if type is a floating-point number, `false` otherwise.
13278
13279
    @complexity Constant.
13280
13281
    @exceptionsafety No-throw guarantee: this member function never throws
13282
    exceptions.
13283
13284
    @liveexample{The following code exemplifies `is_number_float()` for all
13285
    JSON types.,is_number_float}
13286
13287
    @sa @ref is_number() -- check if value is number
13288
    @sa @ref is_number_integer() -- check if value is an integer number
13289
    @sa @ref is_number_unsigned() -- check if value is an unsigned integer
13290
    number
13291
13292
    @since version 1.0.0
13293
    */
13294
    constexpr bool is_number_float() const noexcept
13295
148
    {
13296
148
        return (m_type == value_t::number_float);
13297
148
    }
13298
13299
    /*!
13300
    @brief return whether value is an object
13301
13302
    This function returns true if and only if the JSON value is an object.
13303
13304
    @return `true` if type is object, `false` otherwise.
13305
13306
    @complexity Constant.
13307
13308
    @exceptionsafety No-throw guarantee: this member function never throws
13309
    exceptions.
13310
13311
    @liveexample{The following code exemplifies `is_object()` for all JSON
13312
    types.,is_object}
13313
13314
    @since version 1.0.0
13315
    */
13316
    constexpr bool is_object() const noexcept
13317
261k
    {
13318
261k
        return (m_type == value_t::object);
13319
261k
    }
13320
13321
    /*!
13322
    @brief return whether value is an array
13323
13324
    This function returns true if and only if the JSON value is an array.
13325
13326
    @return `true` if type is array, `false` otherwise.
13327
13328
    @complexity Constant.
13329
13330
    @exceptionsafety No-throw guarantee: this member function never throws
13331
    exceptions.
13332
13333
    @liveexample{The following code exemplifies `is_array()` for all JSON
13334
    types.,is_array}
13335
13336
    @since version 1.0.0
13337
    */
13338
    constexpr bool is_array() const noexcept
13339
514k
    {
13340
514k
        return (m_type == value_t::array);
13341
514k
    }
13342
13343
    /*!
13344
    @brief return whether value is a string
13345
13346
    This function returns true if and only if the JSON value is a string.
13347
13348
    @return `true` if type is string, `false` otherwise.
13349
13350
    @complexity Constant.
13351
13352
    @exceptionsafety No-throw guarantee: this member function never throws
13353
    exceptions.
13354
13355
    @liveexample{The following code exemplifies `is_string()` for all JSON
13356
    types.,is_string}
13357
13358
    @since version 1.0.0
13359
    */
13360
    constexpr bool is_string() const noexcept
13361
22.8k
    {
13362
22.8k
        return (m_type == value_t::string);
13363
22.8k
    }
13364
13365
    /*!
13366
    @brief return whether value is discarded
13367
13368
    This function returns true if and only if the JSON value was discarded
13369
    during parsing with a callback function (see @ref parser_callback_t).
13370
13371
    @note This function will always be `false` for JSON values after parsing.
13372
    That is, discarded values can only occur during parsing, but will be
13373
    removed when inside a structured value or replaced by null in other cases.
13374
13375
    @return `true` if type is discarded, `false` otherwise.
13376
13377
    @complexity Constant.
13378
13379
    @exceptionsafety No-throw guarantee: this member function never throws
13380
    exceptions.
13381
13382
    @liveexample{The following code exemplifies `is_discarded()` for all JSON
13383
    types.,is_discarded}
13384
13385
    @since version 1.0.0
13386
    */
13387
    constexpr bool is_discarded() const noexcept
13388
0
    {
13389
0
        return (m_type == value_t::discarded);
13390
0
    }
13391
13392
    /*!
13393
    @brief return the type of the JSON value (implicit)
13394
13395
    Implicitly return the type of the JSON value as a value from the @ref
13396
    value_t enumeration.
13397
13398
    @return the type of the JSON value
13399
13400
    @complexity Constant.
13401
13402
    @exceptionsafety No-throw guarantee: this member function never throws
13403
    exceptions.
13404
13405
    @liveexample{The following code exemplifies the @ref value_t operator for
13406
    all JSON types.,operator__value_t}
13407
13408
    @sa @ref type() -- return the type of the JSON value (explicit)
13409
    @sa @ref type_name() -- return the type as string
13410
13411
    @since version 1.0.0
13412
    */
13413
    constexpr operator value_t() const noexcept
13414
300
    {
13415
300
        return m_type;
13416
300
    }
13417
13418
    /// @}
13419
13420
  private:
13421
    //////////////////
13422
    // value access //
13423
    //////////////////
13424
13425
    /// get a boolean (explicit)
13426
    boolean_t get_impl(boolean_t* /*unused*/) const
13427
    {
13428
        if (JSON_LIKELY(is_boolean()))
13429
        {
13430
            return m_value.boolean;
13431
        }
13432
13433
        JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name())));
13434
    }
13435
13436
    /// get a pointer to the value (object)
13437
    object_t* get_impl_ptr(object_t* /*unused*/) noexcept
13438
    {
13439
        return is_object() ? m_value.object : nullptr;
13440
    }
13441
13442
    /// get a pointer to the value (object)
13443
    constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
13444
    {
13445
        return is_object() ? m_value.object : nullptr;
13446
    }
13447
13448
    /// get a pointer to the value (array)
13449
    array_t* get_impl_ptr(array_t* /*unused*/) noexcept
13450
    {
13451
        return is_array() ? m_value.array : nullptr;
13452
    }
13453
13454
    /// get a pointer to the value (array)
13455
    constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
13456
    {
13457
        return is_array() ? m_value.array : nullptr;
13458
    }
13459
13460
    /// get a pointer to the value (string)
13461
    string_t* get_impl_ptr(string_t* /*unused*/) noexcept
13462
    {
13463
        return is_string() ? m_value.string : nullptr;
13464
    }
13465
13466
    /// get a pointer to the value (string)
13467
    constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
13468
11.4k
    {
13469
11.4k
        return is_string() ? m_value.string : nullptr;
13470
11.4k
    }
13471
13472
    /// get a pointer to the value (boolean)
13473
    boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
13474
    {
13475
        return is_boolean() ? &m_value.boolean : nullptr;
13476
    }
13477
13478
    /// get a pointer to the value (boolean)
13479
    constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
13480
2
    {
13481
2
        return is_boolean() ? &m_value.boolean : nullptr;
13482
2
    }
13483
13484
    /// get a pointer to the value (integer number)
13485
    number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
13486
    {
13487
        return is_number_integer() ? &m_value.number_integer : nullptr;
13488
    }
13489
13490
    /// get a pointer to the value (integer number)
13491
    constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
13492
0
    {
13493
0
        return is_number_integer() ? &m_value.number_integer : nullptr;
13494
0
    }
13495
13496
    /// get a pointer to the value (unsigned number)
13497
    number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
13498
    {
13499
        return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
13500
    }
13501
13502
    /// get a pointer to the value (unsigned number)
13503
    constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
13504
152
    {
13505
152
        return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
13506
152
    }
13507
13508
    /// get a pointer to the value (floating-point number)
13509
    number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
13510
    {
13511
        return is_number_float() ? &m_value.number_float : nullptr;
13512
    }
13513
13514
    /// get a pointer to the value (floating-point number)
13515
    constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
13516
148
    {
13517
148
        return is_number_float() ? &m_value.number_float : nullptr;
13518
148
    }
13519
13520
    /*!
13521
    @brief helper function to implement get_ref()
13522
13523
    This function helps to implement get_ref() without code duplication for
13524
    const and non-const overloads
13525
13526
    @tparam ThisType will be deduced as `basic_json` or `const basic_json`
13527
13528
    @throw type_error.303 if ReferenceType does not match underlying value
13529
    type of the current JSON
13530
    */
13531
    template<typename ReferenceType, typename ThisType>
13532
    static ReferenceType get_ref_impl(ThisType& obj)
13533
    {
13534
        // delegate the call to get_ptr<>()
13535
        auto ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
13536
13537
        if (JSON_LIKELY(ptr != nullptr))
13538
        {
13539
            return *ptr;
13540
        }
13541
13542
        JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name())));
13543
    }
13544
13545
  public:
13546
    /// @name value access
13547
    /// Direct access to the stored value of a JSON value.
13548
    /// @{
13549
13550
    /*!
13551
    @brief get special-case overload
13552
13553
    This overloads avoids a lot of template boilerplate, it can be seen as the
13554
    identity method
13555
13556
    @tparam BasicJsonType == @ref basic_json
13557
13558
    @return a copy of *this
13559
13560
    @complexity Constant.
13561
13562
    @since version 2.1.0
13563
    */
13564
    template<typename BasicJsonType, detail::enable_if_t<
13565
                 std::is_same<typename std::remove_const<BasicJsonType>::type, basic_json_t>::value,
13566
                 int> = 0>
13567
    basic_json get() const
13568
12
    {
13569
12
        return *this;
13570
12
    }
13571
13572
    /*!
13573
    @brief get special-case overload
13574
13575
    This overloads converts the current @ref basic_json in a different
13576
    @ref basic_json type
13577
13578
    @tparam BasicJsonType == @ref basic_json
13579
13580
    @return a copy of *this, converted into @tparam BasicJsonType
13581
13582
    @complexity Depending on the implementation of the called `from_json()`
13583
                method.
13584
13585
    @since version 3.2.0
13586
    */
13587
    template<typename BasicJsonType, detail::enable_if_t<
13588
                 not std::is_same<BasicJsonType, basic_json>::value and
13589
                 detail::is_basic_json<BasicJsonType>::value, int> = 0>
13590
    BasicJsonType get() const
13591
    {
13592
        return *this;
13593
    }
13594
13595
    /*!
13596
    @brief get a value (explicit)
13597
13598
    Explicit type conversion between the JSON value and a compatible value
13599
    which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
13600
    and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
13601
    The value is converted by calling the @ref json_serializer<ValueType>
13602
    `from_json()` method.
13603
13604
    The function is equivalent to executing
13605
    @code {.cpp}
13606
    ValueType ret;
13607
    JSONSerializer<ValueType>::from_json(*this, ret);
13608
    return ret;
13609
    @endcode
13610
13611
    This overloads is chosen if:
13612
    - @a ValueType is not @ref basic_json,
13613
    - @ref json_serializer<ValueType> has a `from_json()` method of the form
13614
      `void from_json(const basic_json&, ValueType&)`, and
13615
    - @ref json_serializer<ValueType> does not have a `from_json()` method of
13616
      the form `ValueType from_json(const basic_json&)`
13617
13618
    @tparam ValueTypeCV the provided value type
13619
    @tparam ValueType the returned value type
13620
13621
    @return copy of the JSON value, converted to @a ValueType
13622
13623
    @throw what @ref json_serializer<ValueType> `from_json()` method throws
13624
13625
    @liveexample{The example below shows several conversions from JSON values
13626
    to other types. There a few things to note: (1) Floating-point numbers can
13627
    be converted to integers\, (2) A JSON array can be converted to a standard
13628
    `std::vector<short>`\, (3) A JSON object can be converted to C++
13629
    associative containers such as `std::unordered_map<std::string\,
13630
    json>`.,get__ValueType_const}
13631
13632
    @since version 2.1.0
13633
    */
13634
    template<typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,
13635
             detail::enable_if_t <
13636
                 not detail::is_basic_json<ValueType>::value and
13637
                 detail::has_from_json<basic_json_t, ValueType>::value and
13638
                 not detail::has_non_default_from_json<basic_json_t, ValueType>::value,
13639
                 int> = 0>
13640
    ValueType get() const noexcept(noexcept(
13641
                                       JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
13642
11.7k
    {
13643
11.7k
        // we cannot static_assert on ValueTypeCV being non-const, because
13644
11.7k
        // there is support for get<const basic_json_t>(), which is why we
13645
11.7k
        // still need the uncvref
13646
11.7k
        static_assert(not std::is_reference<ValueTypeCV>::value,
13647
11.7k
                      "get() cannot be used with reference types, you might want to use get_ref()");
13648
11.7k
        static_assert(std::is_default_constructible<ValueType>::value,
13649
11.7k
                      "types must be DefaultConstructible when used with get()");
13650
11.7k
13651
11.7k
        ValueType ret;
13652
11.7k
        JSONSerializer<ValueType>::from_json(*this, ret);
13653
11.7k
        return ret;
13654
11.7k
    }
_ZNK8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE3getIbbLi0EEET0_v
Line
Count
Source
13642
2
    {
13643
2
        // we cannot static_assert on ValueTypeCV being non-const, because
13644
2
        // there is support for get<const basic_json_t>(), which is why we
13645
2
        // still need the uncvref
13646
2
        static_assert(not std::is_reference<ValueTypeCV>::value,
13647
2
                      "get() cannot be used with reference types, you might want to use get_ref()");
13648
2
        static_assert(std::is_default_constructible<ValueType>::value,
13649
2
                      "types must be DefaultConstructible when used with get()");
13650
2
13651
2
        ValueType ret;
13652
2
        JSONSerializer<ValueType>::from_json(*this, ret);
13653
2
        return ret;
13654
2
    }
_ZNK8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE3getIS8_S8_Li0EEET0_v
Line
Count
Source
13642
11.4k
    {
13643
11.4k
        // we cannot static_assert on ValueTypeCV being non-const, because
13644
11.4k
        // there is support for get<const basic_json_t>(), which is why we
13645
11.4k
        // still need the uncvref
13646
11.4k
        static_assert(not std::is_reference<ValueTypeCV>::value,
13647
11.4k
                      "get() cannot be used with reference types, you might want to use get_ref()");
13648
11.4k
        static_assert(std::is_default_constructible<ValueType>::value,
13649
11.4k
                      "types must be DefaultConstructible when used with get()");
13650
11.4k
13651
11.4k
        ValueType ret;
13652
11.4k
        JSONSerializer<ValueType>::from_json(*this, ret);
13653
11.4k
        return ret;
13654
11.4k
    }
_ZNK8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE3getIiiLi0EEET0_v
Line
Count
Source
13642
152
    {
13643
152
        // we cannot static_assert on ValueTypeCV being non-const, because
13644
152
        // there is support for get<const basic_json_t>(), which is why we
13645
152
        // still need the uncvref
13646
152
        static_assert(not std::is_reference<ValueTypeCV>::value,
13647
152
                      "get() cannot be used with reference types, you might want to use get_ref()");
13648
152
        static_assert(std::is_default_constructible<ValueType>::value,
13649
152
                      "types must be DefaultConstructible when used with get()");
13650
152
13651
152
        ValueType ret;
13652
152
        JSONSerializer<ValueType>::from_json(*this, ret);
13653
152
        return ret;
13654
152
    }
_ZNK8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE3getIddLi0EEET0_v
Line
Count
Source
13642
148
    {
13643
148
        // we cannot static_assert on ValueTypeCV being non-const, because
13644
148
        // there is support for get<const basic_json_t>(), which is why we
13645
148
        // still need the uncvref
13646
148
        static_assert(not std::is_reference<ValueTypeCV>::value,
13647
148
                      "get() cannot be used with reference types, you might want to use get_ref()");
13648
148
        static_assert(std::is_default_constructible<ValueType>::value,
13649
148
                      "types must be DefaultConstructible when used with get()");
13650
148
13651
148
        ValueType ret;
13652
148
        JSONSerializer<ValueType>::from_json(*this, ret);
13653
148
        return ret;
13654
148
    }
13655
13656
    /*!
13657
    @brief get a value (explicit); special case
13658
13659
    Explicit type conversion between the JSON value and a compatible value
13660
    which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
13661
    and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
13662
    The value is converted by calling the @ref json_serializer<ValueType>
13663
    `from_json()` method.
13664
13665
    The function is equivalent to executing
13666
    @code {.cpp}
13667
    return JSONSerializer<ValueTypeCV>::from_json(*this);
13668
    @endcode
13669
13670
    This overloads is chosen if:
13671
    - @a ValueType is not @ref basic_json and
13672
    - @ref json_serializer<ValueType> has a `from_json()` method of the form
13673
      `ValueType from_json(const basic_json&)`
13674
13675
    @note If @ref json_serializer<ValueType> has both overloads of
13676
    `from_json()`, this one is chosen.
13677
13678
    @tparam ValueTypeCV the provided value type
13679
    @tparam ValueType the returned value type
13680
13681
    @return copy of the JSON value, converted to @a ValueType
13682
13683
    @throw what @ref json_serializer<ValueType> `from_json()` method throws
13684
13685
    @since version 2.1.0
13686
    */
13687
    template<typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,
13688
             detail::enable_if_t<not std::is_same<basic_json_t, ValueType>::value and
13689
                                 detail::has_non_default_from_json<basic_json_t, ValueType>::value,
13690
                                 int> = 0>
13691
    ValueType get() const noexcept(noexcept(
13692
                                       JSONSerializer<ValueTypeCV>::from_json(std::declval<const basic_json_t&>())))
13693
    {
13694
        static_assert(not std::is_reference<ValueTypeCV>::value,
13695
                      "get() cannot be used with reference types, you might want to use get_ref()");
13696
        return JSONSerializer<ValueTypeCV>::from_json(*this);
13697
    }
13698
13699
    /*!
13700
    @brief get a pointer value (explicit)
13701
13702
    Explicit pointer access to the internally stored JSON value. No copies are
13703
    made.
13704
13705
    @warning The pointer becomes invalid if the underlying JSON object
13706
    changes.
13707
13708
    @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
13709
    object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
13710
    @ref number_unsigned_t, or @ref number_float_t.
13711
13712
    @return pointer to the internally stored JSON value if the requested
13713
    pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
13714
13715
    @complexity Constant.
13716
13717
    @liveexample{The example below shows how pointers to internal values of a
13718
    JSON value can be requested. Note that no type conversions are made and a
13719
    `nullptr` is returned if the value and the requested pointer type does not
13720
    match.,get__PointerType}
13721
13722
    @sa @ref get_ptr() for explicit pointer-member access
13723
13724
    @since version 1.0.0
13725
    */
13726
    template<typename PointerType, typename std::enable_if<
13727
                 std::is_pointer<PointerType>::value, int>::type = 0>
13728
    PointerType get() noexcept
13729
    {
13730
        // delegate the call to get_ptr
13731
        return get_ptr<PointerType>();
13732
    }
13733
13734
    /*!
13735
    @brief get a pointer value (explicit)
13736
    @copydoc get()
13737
    */
13738
    template<typename PointerType, typename std::enable_if<
13739
                 std::is_pointer<PointerType>::value, int>::type = 0>
13740
    constexpr const PointerType get() const noexcept
13741
    {
13742
        // delegate the call to get_ptr
13743
        return get_ptr<PointerType>();
13744
    }
13745
13746
    /*!
13747
    @brief get a pointer value (implicit)
13748
13749
    Implicit pointer access to the internally stored JSON value. No copies are
13750
    made.
13751
13752
    @warning Writing data to the pointee of the result yields an undefined
13753
    state.
13754
13755
    @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
13756
    object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
13757
    @ref number_unsigned_t, or @ref number_float_t. Enforced by a static
13758
    assertion.
13759
13760
    @return pointer to the internally stored JSON value if the requested
13761
    pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
13762
13763
    @complexity Constant.
13764
13765
    @liveexample{The example below shows how pointers to internal values of a
13766
    JSON value can be requested. Note that no type conversions are made and a
13767
    `nullptr` is returned if the value and the requested pointer type does not
13768
    match.,get_ptr}
13769
13770
    @since version 1.0.0
13771
    */
13772
    template<typename PointerType, typename std::enable_if<
13773
                 std::is_pointer<PointerType>::value, int>::type = 0>
13774
    PointerType get_ptr() noexcept
13775
    {
13776
        // get the type of the PointerType (remove pointer and const)
13777
        using pointee_t = typename std::remove_const<typename
13778
                          std::remove_pointer<typename
13779
                          std::remove_const<PointerType>::type>::type>::type;
13780
        // make sure the type matches the allowed types
13781
        static_assert(
13782
            std::is_same<object_t, pointee_t>::value
13783
            or std::is_same<array_t, pointee_t>::value
13784
            or std::is_same<string_t, pointee_t>::value
13785
            or std::is_same<boolean_t, pointee_t>::value
13786
            or std::is_same<number_integer_t, pointee_t>::value
13787
            or std::is_same<number_unsigned_t, pointee_t>::value
13788
            or std::is_same<number_float_t, pointee_t>::value
13789
            , "incompatible pointer type");
13790
13791
        // delegate the call to get_impl_ptr<>()
13792
        return get_impl_ptr(static_cast<PointerType>(nullptr));
13793
    }
13794
13795
    /*!
13796
    @brief get a pointer value (implicit)
13797
    @copydoc get_ptr()
13798
    */
13799
    template<typename PointerType, typename std::enable_if<
13800
                 std::is_pointer<PointerType>::value and
13801
                 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int>::type = 0>
13802
    constexpr const PointerType get_ptr() const noexcept
13803
11.7k
    {
13804
11.7k
        // get the type of the PointerType (remove pointer and const)
13805
11.7k
        using pointee_t = typename std::remove_const<typename
13806
11.7k
                          std::remove_pointer<typename
13807
11.7k
                          std::remove_const<PointerType>::type>::type>::type;
13808
11.7k
        // make sure the type matches the allowed types
13809
11.7k
        static_assert(
13810
11.7k
            std::is_same<object_t, pointee_t>::value
13811
11.7k
            or std::is_same<array_t, pointee_t>::value
13812
11.7k
            or std::is_same<string_t, pointee_t>::value
13813
11.7k
            or std::is_same<boolean_t, pointee_t>::value
13814
11.7k
            or std::is_same<number_integer_t, pointee_t>::value
13815
11.7k
            or std::is_same<number_unsigned_t, pointee_t>::value
13816
11.7k
            or std::is_same<number_float_t, pointee_t>::value
13817
11.7k
            , "incompatible pointer type");
13818
11.7k
13819
11.7k
        // delegate the call to get_impl_ptr<>() const
13820
11.7k
        return get_impl_ptr(static_cast<PointerType>(nullptr));
13821
11.7k
    }
_ZNK8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE7get_ptrIPKbLi0EEEKT_v
Line
Count
Source
13803
2
    {
13804
2
        // get the type of the PointerType (remove pointer and const)
13805
2
        using pointee_t = typename std::remove_const<typename
13806
2
                          std::remove_pointer<typename
13807
2
                          std::remove_const<PointerType>::type>::type>::type;
13808
2
        // make sure the type matches the allowed types
13809
2
        static_assert(
13810
2
            std::is_same<object_t, pointee_t>::value
13811
2
            or std::is_same<array_t, pointee_t>::value
13812
2
            or std::is_same<string_t, pointee_t>::value
13813
2
            or std::is_same<boolean_t, pointee_t>::value
13814
2
            or std::is_same<number_integer_t, pointee_t>::value
13815
2
            or std::is_same<number_unsigned_t, pointee_t>::value
13816
2
            or std::is_same<number_float_t, pointee_t>::value
13817
2
            , "incompatible pointer type");
13818
2
13819
2
        // delegate the call to get_impl_ptr<>() const
13820
2
        return get_impl_ptr(static_cast<PointerType>(nullptr));
13821
2
    }
_ZNK8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE7get_ptrIPKS8_Li0EEEKT_v
Line
Count
Source
13803
11.4k
    {
13804
11.4k
        // get the type of the PointerType (remove pointer and const)
13805
11.4k
        using pointee_t = typename std::remove_const<typename
13806
11.4k
                          std::remove_pointer<typename
13807
11.4k
                          std::remove_const<PointerType>::type>::type>::type;
13808
11.4k
        // make sure the type matches the allowed types
13809
11.4k
        static_assert(
13810
11.4k
            std::is_same<object_t, pointee_t>::value
13811
11.4k
            or std::is_same<array_t, pointee_t>::value
13812
11.4k
            or std::is_same<string_t, pointee_t>::value
13813
11.4k
            or std::is_same<boolean_t, pointee_t>::value
13814
11.4k
            or std::is_same<number_integer_t, pointee_t>::value
13815
11.4k
            or std::is_same<number_unsigned_t, pointee_t>::value
13816
11.4k
            or std::is_same<number_float_t, pointee_t>::value
13817
11.4k
            , "incompatible pointer type");
13818
11.4k
13819
11.4k
        // delegate the call to get_impl_ptr<>() const
13820
11.4k
        return get_impl_ptr(static_cast<PointerType>(nullptr));
13821
11.4k
    }
_ZNK8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE7get_ptrIPKmLi0EEEKT_v
Line
Count
Source
13803
152
    {
13804
152
        // get the type of the PointerType (remove pointer and const)
13805
152
        using pointee_t = typename std::remove_const<typename
13806
152
                          std::remove_pointer<typename
13807
152
                          std::remove_const<PointerType>::type>::type>::type;
13808
152
        // make sure the type matches the allowed types
13809
152
        static_assert(
13810
152
            std::is_same<object_t, pointee_t>::value
13811
152
            or std::is_same<array_t, pointee_t>::value
13812
152
            or std::is_same<string_t, pointee_t>::value
13813
152
            or std::is_same<boolean_t, pointee_t>::value
13814
152
            or std::is_same<number_integer_t, pointee_t>::value
13815
152
            or std::is_same<number_unsigned_t, pointee_t>::value
13816
152
            or std::is_same<number_float_t, pointee_t>::value
13817
152
            , "incompatible pointer type");
13818
152
13819
152
        // delegate the call to get_impl_ptr<>() const
13820
152
        return get_impl_ptr(static_cast<PointerType>(nullptr));
13821
152
    }
Unexecuted instantiation: _ZNK8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE7get_ptrIPKlLi0EEEKT_v
_ZNK8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE7get_ptrIPKdLi0EEEKT_v
Line
Count
Source
13803
148
    {
13804
148
        // get the type of the PointerType (remove pointer and const)
13805
148
        using pointee_t = typename std::remove_const<typename
13806
148
                          std::remove_pointer<typename
13807
148
                          std::remove_const<PointerType>::type>::type>::type;
13808
148
        // make sure the type matches the allowed types
13809
148
        static_assert(
13810
148
            std::is_same<object_t, pointee_t>::value
13811
148
            or std::is_same<array_t, pointee_t>::value
13812
148
            or std::is_same<string_t, pointee_t>::value
13813
148
            or std::is_same<boolean_t, pointee_t>::value
13814
148
            or std::is_same<number_integer_t, pointee_t>::value
13815
148
            or std::is_same<number_unsigned_t, pointee_t>::value
13816
148
            or std::is_same<number_float_t, pointee_t>::value
13817
148
            , "incompatible pointer type");
13818
148
13819
148
        // delegate the call to get_impl_ptr<>() const
13820
148
        return get_impl_ptr(static_cast<PointerType>(nullptr));
13821
148
    }
13822
13823
    /*!
13824
    @brief get a reference value (implicit)
13825
13826
    Implicit reference access to the internally stored JSON value. No copies
13827
    are made.
13828
13829
    @warning Writing data to the referee of the result yields an undefined
13830
    state.
13831
13832
    @tparam ReferenceType reference type; must be a reference to @ref array_t,
13833
    @ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or
13834
    @ref number_float_t. Enforced by static assertion.
13835
13836
    @return reference to the internally stored JSON value if the requested
13837
    reference type @a ReferenceType fits to the JSON value; throws
13838
    type_error.303 otherwise
13839
13840
    @throw type_error.303 in case passed type @a ReferenceType is incompatible
13841
    with the stored JSON value; see example below
13842
13843
    @complexity Constant.
13844
13845
    @liveexample{The example shows several calls to `get_ref()`.,get_ref}
13846
13847
    @since version 1.1.0
13848
    */
13849
    template<typename ReferenceType, typename std::enable_if<
13850
                 std::is_reference<ReferenceType>::value, int>::type = 0>
13851
    ReferenceType get_ref()
13852
    {
13853
        // delegate call to get_ref_impl
13854
        return get_ref_impl<ReferenceType>(*this);
13855
    }
13856
13857
    /*!
13858
    @brief get a reference value (implicit)
13859
    @copydoc get_ref()
13860
    */
13861
    template<typename ReferenceType, typename std::enable_if<
13862
                 std::is_reference<ReferenceType>::value and
13863
                 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int>::type = 0>
13864
    ReferenceType get_ref() const
13865
    {
13866
        // delegate call to get_ref_impl
13867
        return get_ref_impl<ReferenceType>(*this);
13868
    }
13869
13870
    /*!
13871
    @brief get a value (implicit)
13872
13873
    Implicit type conversion between the JSON value and a compatible value.
13874
    The call is realized by calling @ref get() const.
13875
13876
    @tparam ValueType non-pointer type compatible to the JSON value, for
13877
    instance `int` for JSON integer numbers, `bool` for JSON booleans, or
13878
    `std::vector` types for JSON arrays. The character type of @ref string_t
13879
    as well as an initializer list of this type is excluded to avoid
13880
    ambiguities as these types implicitly convert to `std::string`.
13881
13882
    @return copy of the JSON value, converted to type @a ValueType
13883
13884
    @throw type_error.302 in case passed type @a ValueType is incompatible
13885
    to the JSON value type (e.g., the JSON value is of type boolean, but a
13886
    string is requested); see example below
13887
13888
    @complexity Linear in the size of the JSON value.
13889
13890
    @liveexample{The example below shows several conversions from JSON values
13891
    to other types. There a few things to note: (1) Floating-point numbers can
13892
    be converted to integers\, (2) A JSON array can be converted to a standard
13893
    `std::vector<short>`\, (3) A JSON object can be converted to C++
13894
    associative containers such as `std::unordered_map<std::string\,
13895
    json>`.,operator__ValueType}
13896
13897
    @since version 1.0.0
13898
    */
13899
    template < typename ValueType, typename std::enable_if <
13900
                   not std::is_pointer<ValueType>::value and
13901
                   not std::is_same<ValueType, detail::json_ref<basic_json>>::value and
13902
                   not std::is_same<ValueType, typename string_t::value_type>::value and
13903
                   not detail::is_basic_json<ValueType>::value
13904
#ifndef _MSC_VER  // fix for issue #167 operator<< ambiguity under VS2015
13905
                   and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
13906
#if defined(JSON_HAS_CPP_17) && defined(_MSC_VER) and _MSC_VER <= 1914
13907
                   and not std::is_same<ValueType, typename std::string_view>::value
13908
#endif
13909
#endif
13910
                   , int >::type = 0 >
13911
    operator ValueType() const
13912
    {
13913
        // delegate the call to get<>() const
13914
        return get<ValueType>();
13915
    }
13916
13917
    /// @}
13918
13919
13920
    ////////////////////
13921
    // element access //
13922
    ////////////////////
13923
13924
    /// @name element access
13925
    /// Access to the JSON value.
13926
    /// @{
13927
13928
    /*!
13929
    @brief access specified array element with bounds checking
13930
13931
    Returns a reference to the element at specified location @a idx, with
13932
    bounds checking.
13933
13934
    @param[in] idx  index of the element to access
13935
13936
    @return reference to the element at index @a idx
13937
13938
    @throw type_error.304 if the JSON value is not an array; in this case,
13939
    calling `at` with an index makes no sense. See example below.
13940
    @throw out_of_range.401 if the index @a idx is out of range of the array;
13941
    that is, `idx >= size()`. See example below.
13942
13943
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
13944
    changes in the JSON value.
13945
13946
    @complexity Constant.
13947
13948
    @since version 1.0.0
13949
13950
    @liveexample{The example below shows how array elements can be read and
13951
    written using `at()`. It also demonstrates the different exceptions that
13952
    can be thrown.,at__size_type}
13953
    */
13954
    reference at(size_type idx)
13955
    {
13956
        // at only works for arrays
13957
        if (JSON_LIKELY(is_array()))
13958
        {
13959
            JSON_TRY
13960
            {
13961
                return m_value.array->at(idx);
13962
            }
13963
            JSON_CATCH (std::out_of_range&)
13964
            {
13965
                // create better exception explanation
13966
                JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
13967
            }
13968
        }
13969
        else
13970
        {
13971
            JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
13972
        }
13973
    }
13974
13975
    /*!
13976
    @brief access specified array element with bounds checking
13977
13978
    Returns a const reference to the element at specified location @a idx,
13979
    with bounds checking.
13980
13981
    @param[in] idx  index of the element to access
13982
13983
    @return const reference to the element at index @a idx
13984
13985
    @throw type_error.304 if the JSON value is not an array; in this case,
13986
    calling `at` with an index makes no sense. See example below.
13987
    @throw out_of_range.401 if the index @a idx is out of range of the array;
13988
    that is, `idx >= size()`. See example below.
13989
13990
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
13991
    changes in the JSON value.
13992
13993
    @complexity Constant.
13994
13995
    @since version 1.0.0
13996
13997
    @liveexample{The example below shows how array elements can be read using
13998
    `at()`. It also demonstrates the different exceptions that can be thrown.,
13999
    at__size_type_const}
14000
    */
14001
    const_reference at(size_type idx) const
14002
    {
14003
        // at only works for arrays
14004
        if (JSON_LIKELY(is_array()))
14005
        {
14006
            JSON_TRY
14007
            {
14008
                return m_value.array->at(idx);
14009
            }
14010
            JSON_CATCH (std::out_of_range&)
14011
            {
14012
                // create better exception explanation
14013
                JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
14014
            }
14015
        }
14016
        else
14017
        {
14018
            JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
14019
        }
14020
    }
14021
14022
    /*!
14023
    @brief access specified object element with bounds checking
14024
14025
    Returns a reference to the element at with specified key @a key, with
14026
    bounds checking.
14027
14028
    @param[in] key  key of the element to access
14029
14030
    @return reference to the element at key @a key
14031
14032
    @throw type_error.304 if the JSON value is not an object; in this case,
14033
    calling `at` with a key makes no sense. See example below.
14034
    @throw out_of_range.403 if the key @a key is is not stored in the object;
14035
    that is, `find(key) == end()`. See example below.
14036
14037
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
14038
    changes in the JSON value.
14039
14040
    @complexity Logarithmic in the size of the container.
14041
14042
    @sa @ref operator[](const typename object_t::key_type&) for unchecked
14043
    access by reference
14044
    @sa @ref value() for access by value with a default value
14045
14046
    @since version 1.0.0
14047
14048
    @liveexample{The example below shows how object elements can be read and
14049
    written using `at()`. It also demonstrates the different exceptions that
14050
    can be thrown.,at__object_t_key_type}
14051
    */
14052
    reference at(const typename object_t::key_type& key)
14053
12.6k
    {
14054
12.6k
        // at only works for objects
14055
12.6k
        if (JSON_LIKELY(is_object()))
14056
12.6k
        {
14057
12.6k
            JSON_TRY
14058
12.6k
            {
14059
12.6k
                return m_value.object->at(key);
14060
12.6k
            }
14061
12.6k
            JSON_CATCH (std::out_of_range&)
14062
12.6k
            {
14063
1
                // create better exception explanation
14064
1
                JSON_THROW(out_of_range::create(403, "key '" + key + "' not found"));
14065
1
            }
14066
12.6k
        }
14067
12.6k
        else
14068
12.6k
        {
14069
0
            JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
14070
0
        }
14071
12.6k
    }
14072
14073
    /*!
14074
    @brief access specified object element with bounds checking
14075
14076
    Returns a const reference to the element at with specified key @a key,
14077
    with bounds checking.
14078
14079
    @param[in] key  key of the element to access
14080
14081
    @return const reference to the element at key @a key
14082
14083
    @throw type_error.304 if the JSON value is not an object; in this case,
14084
    calling `at` with a key makes no sense. See example below.
14085
    @throw out_of_range.403 if the key @a key is is not stored in the object;
14086
    that is, `find(key) == end()`. See example below.
14087
14088
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
14089
    changes in the JSON value.
14090
14091
    @complexity Logarithmic in the size of the container.
14092
14093
    @sa @ref operator[](const typename object_t::key_type&) for unchecked
14094
    access by reference
14095
    @sa @ref value() for access by value with a default value
14096
14097
    @since version 1.0.0
14098
14099
    @liveexample{The example below shows how object elements can be read using
14100
    `at()`. It also demonstrates the different exceptions that can be thrown.,
14101
    at__object_t_key_type_const}
14102
    */
14103
    const_reference at(const typename object_t::key_type& key) const
14104
    {
14105
        // at only works for objects
14106
        if (JSON_LIKELY(is_object()))
14107
        {
14108
            JSON_TRY
14109
            {
14110
                return m_value.object->at(key);
14111
            }
14112
            JSON_CATCH (std::out_of_range&)
14113
            {
14114
                // create better exception explanation
14115
                JSON_THROW(out_of_range::create(403, "key '" + key + "' not found"));
14116
            }
14117
        }
14118
        else
14119
        {
14120
            JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
14121
        }
14122
    }
14123
14124
    /*!
14125
    @brief access specified array element
14126
14127
    Returns a reference to the element at specified location @a idx.
14128
14129
    @note If @a idx is beyond the range of the array (i.e., `idx >= size()`),
14130
    then the array is silently filled up with `null` values to make `idx` a
14131
    valid reference to the last stored element.
14132
14133
    @param[in] idx  index of the element to access
14134
14135
    @return reference to the element at index @a idx
14136
14137
    @throw type_error.305 if the JSON value is not an array or null; in that
14138
    cases, using the [] operator with an index makes no sense.
14139
14140
    @complexity Constant if @a idx is in the range of the array. Otherwise
14141
    linear in `idx - size()`.
14142
14143
    @liveexample{The example below shows how array elements can be read and
14144
    written using `[]` operator. Note the addition of `null`
14145
    values.,operatorarray__size_type}
14146
14147
    @since version 1.0.0
14148
    */
14149
    reference operator[](size_type idx)
14150
    {
14151
        // implicitly convert null value to an empty array
14152
        if (is_null())
14153
        {
14154
            m_type = value_t::array;
14155
            m_value.array = create<array_t>();
14156
            assert_invariant();
14157
        }
14158
14159
        // operator[] only works for arrays
14160
        if (JSON_LIKELY(is_array()))
14161
        {
14162
            // fill up array with null values if given idx is outside range
14163
            if (idx >= m_value.array->size())
14164
            {
14165
                m_value.array->insert(m_value.array->end(),
14166
                                      idx - m_value.array->size() + 1,
14167
                                      basic_json());
14168
            }
14169
14170
            return m_value.array->operator[](idx);
14171
        }
14172
14173
        JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name())));
14174
    }
14175
14176
    /*!
14177
    @brief access specified array element
14178
14179
    Returns a const reference to the element at specified location @a idx.
14180
14181
    @param[in] idx  index of the element to access
14182
14183
    @return const reference to the element at index @a idx
14184
14185
    @throw type_error.305 if the JSON value is not an array; in that case,
14186
    using the [] operator with an index makes no sense.
14187
14188
    @complexity Constant.
14189
14190
    @liveexample{The example below shows how array elements can be read using
14191
    the `[]` operator.,operatorarray__size_type_const}
14192
14193
    @since version 1.0.0
14194
    */
14195
    const_reference operator[](size_type idx) const
14196
    {
14197
        // const operator[] only works for arrays
14198
        if (JSON_LIKELY(is_array()))
14199
        {
14200
            return m_value.array->operator[](idx);
14201
        }
14202
14203
        JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name())));
14204
    }
14205
14206
    /*!
14207
    @brief access specified object element
14208
14209
    Returns a reference to the element at with specified key @a key.
14210
14211
    @note If @a key is not found in the object, then it is silently added to
14212
    the object and filled with a `null` value to make `key` a valid reference.
14213
    In case the value was `null` before, it is converted to an object.
14214
14215
    @param[in] key  key of the element to access
14216
14217
    @return reference to the element at key @a key
14218
14219
    @throw type_error.305 if the JSON value is not an object or null; in that
14220
    cases, using the [] operator with a key makes no sense.
14221
14222
    @complexity Logarithmic in the size of the container.
14223
14224
    @liveexample{The example below shows how object elements can be read and
14225
    written using the `[]` operator.,operatorarray__key_type}
14226
14227
    @sa @ref at(const typename object_t::key_type&) for access by reference
14228
    with range checking
14229
    @sa @ref value() for access by value with a default value
14230
14231
    @since version 1.0.0
14232
    */
14233
    reference operator[](const typename object_t::key_type& key)
14234
307
    {
14235
307
        // implicitly convert null value to an empty object
14236
307
        if (is_null())
14237
307
        {
14238
77
            m_type = value_t::object;
14239
77
            m_value.object = create<object_t>();
14240
77
            assert_invariant();
14241
77
        }
14242
307
14243
307
        // operator[] only works for objects
14244
307
        if (JSON_LIKELY(is_object()))
14245
307
        {
14246
307
            return m_value.object->operator[](key);
14247
307
        }
14248
307
14249
307
        JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
14250
307
    }
14251
14252
    /*!
14253
    @brief read-only access specified object element
14254
14255
    Returns a const reference to the element at with specified key @a key. No
14256
    bounds checking is performed.
14257
14258
    @warning If the element with key @a key does not exist, the behavior is
14259
    undefined.
14260
14261
    @param[in] key  key of the element to access
14262
14263
    @return const reference to the element at key @a key
14264
14265
    @pre The element with key @a key must exist. **This precondition is
14266
         enforced with an assertion.**
14267
14268
    @throw type_error.305 if the JSON value is not an object; in that case,
14269
    using the [] operator with a key makes no sense.
14270
14271
    @complexity Logarithmic in the size of the container.
14272
14273
    @liveexample{The example below shows how object elements can be read using
14274
    the `[]` operator.,operatorarray__key_type_const}
14275
14276
    @sa @ref at(const typename object_t::key_type&) for access by reference
14277
    with range checking
14278
    @sa @ref value() for access by value with a default value
14279
14280
    @since version 1.0.0
14281
    */
14282
    const_reference operator[](const typename object_t::key_type& key) const
14283
    {
14284
        // const operator[] only works for objects
14285
        if (JSON_LIKELY(is_object()))
14286
        {
14287
            assert(m_value.object->find(key) != m_value.object->end());
14288
            return m_value.object->find(key)->second;
14289
        }
14290
14291
        JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
14292
    }
14293
14294
    /*!
14295
    @brief access specified object element
14296
14297
    Returns a reference to the element at with specified key @a key.
14298
14299
    @note If @a key is not found in the object, then it is silently added to
14300
    the object and filled with a `null` value to make `key` a valid reference.
14301
    In case the value was `null` before, it is converted to an object.
14302
14303
    @param[in] key  key of the element to access
14304
14305
    @return reference to the element at key @a key
14306
14307
    @throw type_error.305 if the JSON value is not an object or null; in that
14308
    cases, using the [] operator with a key makes no sense.
14309
14310
    @complexity Logarithmic in the size of the container.
14311
14312
    @liveexample{The example below shows how object elements can be read and
14313
    written using the `[]` operator.,operatorarray__key_type}
14314
14315
    @sa @ref at(const typename object_t::key_type&) for access by reference
14316
    with range checking
14317
    @sa @ref value() for access by value with a default value
14318
14319
    @since version 1.1.0
14320
    */
14321
    template<typename T>
14322
    reference operator[](T* key)
14323
1.32k
    {
14324
1.32k
        // implicitly convert null to object
14325
1.32k
        if (is_null())
14326
1.32k
        {
14327
267
            m_type = value_t::object;
14328
267
            m_value = value_t::object;
14329
267
            assert_invariant();
14330
267
        }
14331
1.32k
14332
1.32k
        // at only works for objects
14333
1.32k
        if (JSON_LIKELY(is_object()))
14334
1.32k
        {
14335
1.32k
            return m_value.object->operator[](key);
14336
1.32k
        }
14337
1.32k
14338
1.32k
        JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
14339
1.32k
    }
14340
14341
    /*!
14342
    @brief read-only access specified object element
14343
14344
    Returns a const reference to the element at with specified key @a key. No
14345
    bounds checking is performed.
14346
14347
    @warning If the element with key @a key does not exist, the behavior is
14348
    undefined.
14349
14350
    @param[in] key  key of the element to access
14351
14352
    @return const reference to the element at key @a key
14353
14354
    @pre The element with key @a key must exist. **This precondition is
14355
         enforced with an assertion.**
14356
14357
    @throw type_error.305 if the JSON value is not an object; in that case,
14358
    using the [] operator with a key makes no sense.
14359
14360
    @complexity Logarithmic in the size of the container.
14361
14362
    @liveexample{The example below shows how object elements can be read using
14363
    the `[]` operator.,operatorarray__key_type_const}
14364
14365
    @sa @ref at(const typename object_t::key_type&) for access by reference
14366
    with range checking
14367
    @sa @ref value() for access by value with a default value
14368
14369
    @since version 1.1.0
14370
    */
14371
    template<typename T>
14372
    const_reference operator[](T* key) const
14373
    {
14374
        // at only works for objects
14375
        if (JSON_LIKELY(is_object()))
14376
        {
14377
            assert(m_value.object->find(key) != m_value.object->end());
14378
            return m_value.object->find(key)->second;
14379
        }
14380
14381
        JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
14382
    }
14383
14384
    /*!
14385
    @brief access specified object element with default value
14386
14387
    Returns either a copy of an object's element at the specified key @a key
14388
    or a given default value if no element with key @a key exists.
14389
14390
    The function is basically equivalent to executing
14391
    @code {.cpp}
14392
    try {
14393
        return at(key);
14394
    } catch(out_of_range) {
14395
        return default_value;
14396
    }
14397
    @endcode
14398
14399
    @note Unlike @ref at(const typename object_t::key_type&), this function
14400
    does not throw if the given key @a key was not found.
14401
14402
    @note Unlike @ref operator[](const typename object_t::key_type& key), this
14403
    function does not implicitly add an element to the position defined by @a
14404
    key. This function is furthermore also applicable to const objects.
14405
14406
    @param[in] key  key of the element to access
14407
    @param[in] default_value  the value to return if @a key is not found
14408
14409
    @tparam ValueType type compatible to JSON values, for instance `int` for
14410
    JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for
14411
    JSON arrays. Note the type of the expected value at @a key and the default
14412
    value @a default_value must be compatible.
14413
14414
    @return copy of the element at key @a key or @a default_value if @a key
14415
    is not found
14416
14417
    @throw type_error.306 if the JSON value is not an object; in that case,
14418
    using `value()` with a key makes no sense.
14419
14420
    @complexity Logarithmic in the size of the container.
14421
14422
    @liveexample{The example below shows how object elements can be queried
14423
    with a default value.,basic_json__value}
14424
14425
    @sa @ref at(const typename object_t::key_type&) for access by reference
14426
    with range checking
14427
    @sa @ref operator[](const typename object_t::key_type&) for unchecked
14428
    access by reference
14429
14430
    @since version 1.0.0
14431
    */
14432
    template<class ValueType, typename std::enable_if<
14433
                 std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
14434
    ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
14435
    {
14436
        // at only works for objects
14437
        if (JSON_LIKELY(is_object()))
14438
        {
14439
            // if key is found, return value and given default value otherwise
14440
            const auto it = find(key);
14441
            if (it != end())
14442
            {
14443
                return *it;
14444
            }
14445
14446
            return default_value;
14447
        }
14448
14449
        JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name())));
14450
    }
14451
14452
    /*!
14453
    @brief overload for a default value of type const char*
14454
    @copydoc basic_json::value(const typename object_t::key_type&, ValueType) const
14455
    */
14456
    string_t value(const typename object_t::key_type& key, const char* default_value) const
14457
    {
14458
        return value(key, string_t(default_value));
14459
    }
14460
14461
    /*!
14462
    @brief access specified object element via JSON Pointer with default value
14463
14464
    Returns either a copy of an object's element at the specified key @a key
14465
    or a given default value if no element with key @a key exists.
14466
14467
    The function is basically equivalent to executing
14468
    @code {.cpp}
14469
    try {
14470
        return at(ptr);
14471
    } catch(out_of_range) {
14472
        return default_value;
14473
    }
14474
    @endcode
14475
14476
    @note Unlike @ref at(const json_pointer&), this function does not throw
14477
    if the given key @a key was not found.
14478
14479
    @param[in] ptr  a JSON pointer to the element to access
14480
    @param[in] default_value  the value to return if @a ptr found no value
14481
14482
    @tparam ValueType type compatible to JSON values, for instance `int` for
14483
    JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for
14484
    JSON arrays. Note the type of the expected value at @a key and the default
14485
    value @a default_value must be compatible.
14486
14487
    @return copy of the element at key @a key or @a default_value if @a key
14488
    is not found
14489
14490
    @throw type_error.306 if the JSON value is not an object; in that case,
14491
    using `value()` with a key makes no sense.
14492
14493
    @complexity Logarithmic in the size of the container.
14494
14495
    @liveexample{The example below shows how object elements can be queried
14496
    with a default value.,basic_json__value_ptr}
14497
14498
    @sa @ref operator[](const json_pointer&) for unchecked access by reference
14499
14500
    @since version 2.0.2
14501
    */
14502
    template<class ValueType, typename std::enable_if<
14503
                 std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
14504
    ValueType value(const json_pointer& ptr, const ValueType& default_value) const
14505
    {
14506
        // at only works for objects
14507
        if (JSON_LIKELY(is_object()))
14508
        {
14509
            // if pointer resolves a value, return it or use default value
14510
            JSON_TRY
14511
            {
14512
                return ptr.get_checked(this);
14513
            }
14514
            JSON_INTERNAL_CATCH (out_of_range&)
14515
            {
14516
                return default_value;
14517
            }
14518
        }
14519
14520
        JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name())));
14521
    }
14522
14523
    /*!
14524
    @brief overload for a default value of type const char*
14525
    @copydoc basic_json::value(const json_pointer&, ValueType) const
14526
    */
14527
    string_t value(const json_pointer& ptr, const char* default_value) const
14528
    {
14529
        return value(ptr, string_t(default_value));
14530
    }
14531
14532
    /*!
14533
    @brief access the first element
14534
14535
    Returns a reference to the first element in the container. For a JSON
14536
    container `c`, the expression `c.front()` is equivalent to `*c.begin()`.
14537
14538
    @return In case of a structured type (array or object), a reference to the
14539
    first element is returned. In case of number, string, or boolean values, a
14540
    reference to the value is returned.
14541
14542
    @complexity Constant.
14543
14544
    @pre The JSON value must not be `null` (would throw `std::out_of_range`)
14545
    or an empty array or object (undefined behavior, **guarded by
14546
    assertions**).
14547
    @post The JSON value remains unchanged.
14548
14549
    @throw invalid_iterator.214 when called on `null` value
14550
14551
    @liveexample{The following code shows an example for `front()`.,front}
14552
14553
    @sa @ref back() -- access the last element
14554
14555
    @since version 1.0.0
14556
    */
14557
    reference front()
14558
    {
14559
        return *begin();
14560
    }
14561
14562
    /*!
14563
    @copydoc basic_json::front()
14564
    */
14565
    const_reference front() const
14566
    {
14567
        return *cbegin();
14568
    }
14569
14570
    /*!
14571
    @brief access the last element
14572
14573
    Returns a reference to the last element in the container. For a JSON
14574
    container `c`, the expression `c.back()` is equivalent to
14575
    @code {.cpp}
14576
    auto tmp = c.end();
14577
    --tmp;
14578
    return *tmp;
14579
    @endcode
14580
14581
    @return In case of a structured type (array or object), a reference to the
14582
    last element is returned. In case of number, string, or boolean values, a
14583
    reference to the value is returned.
14584
14585
    @complexity Constant.
14586
14587
    @pre The JSON value must not be `null` (would throw `std::out_of_range`)
14588
    or an empty array or object (undefined behavior, **guarded by
14589
    assertions**).
14590
    @post The JSON value remains unchanged.
14591
14592
    @throw invalid_iterator.214 when called on a `null` value. See example
14593
    below.
14594
14595
    @liveexample{The following code shows an example for `back()`.,back}
14596
14597
    @sa @ref front() -- access the first element
14598
14599
    @since version 1.0.0
14600
    */
14601
    reference back()
14602
    {
14603
        auto tmp = end();
14604
        --tmp;
14605
        return *tmp;
14606
    }
14607
14608
    /*!
14609
    @copydoc basic_json::back()
14610
    */
14611
    const_reference back() const
14612
    {
14613
        auto tmp = cend();
14614
        --tmp;
14615
        return *tmp;
14616
    }
14617
14618
    /*!
14619
    @brief remove element given an iterator
14620
14621
    Removes the element specified by iterator @a pos. The iterator @a pos must
14622
    be valid and dereferenceable. Thus the `end()` iterator (which is valid,
14623
    but is not dereferenceable) cannot be used as a value for @a pos.
14624
14625
    If called on a primitive type other than `null`, the resulting JSON value
14626
    will be `null`.
14627
14628
    @param[in] pos iterator to the element to remove
14629
    @return Iterator following the last removed element. If the iterator @a
14630
    pos refers to the last element, the `end()` iterator is returned.
14631
14632
    @tparam IteratorType an @ref iterator or @ref const_iterator
14633
14634
    @post Invalidates iterators and references at or after the point of the
14635
    erase, including the `end()` iterator.
14636
14637
    @throw type_error.307 if called on a `null` value; example: `"cannot use
14638
    erase() with null"`
14639
    @throw invalid_iterator.202 if called on an iterator which does not belong
14640
    to the current JSON value; example: `"iterator does not fit current
14641
    value"`
14642
    @throw invalid_iterator.205 if called on a primitive type with invalid
14643
    iterator (i.e., any iterator which is not `begin()`); example: `"iterator
14644
    out of range"`
14645
14646
    @complexity The complexity depends on the type:
14647
    - objects: amortized constant
14648
    - arrays: linear in distance between @a pos and the end of the container
14649
    - strings: linear in the length of the string
14650
    - other types: constant
14651
14652
    @liveexample{The example shows the result of `erase()` for different JSON
14653
    types.,erase__IteratorType}
14654
14655
    @sa @ref erase(IteratorType, IteratorType) -- removes the elements in
14656
    the given range
14657
    @sa @ref erase(const typename object_t::key_type&) -- removes the element
14658
    from an object at the given key
14659
    @sa @ref erase(const size_type) -- removes the element from an array at
14660
    the given index
14661
14662
    @since version 1.0.0
14663
    */
14664
    template<class IteratorType, typename std::enable_if<
14665
                 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
14666
                 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
14667
             = 0>
14668
    IteratorType erase(IteratorType pos)
14669
0
    {
14670
0
        // make sure iterator fits the current value
14671
0
        if (JSON_UNLIKELY(this != pos.m_object))
14672
0
        {
14673
0
            JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
14674
0
        }
14675
0
14676
0
        IteratorType result = end();
14677
0
14678
0
        switch (m_type)
14679
0
        {
14680
0
            case value_t::boolean:
14681
0
            case value_t::number_float:
14682
0
            case value_t::number_integer:
14683
0
            case value_t::number_unsigned:
14684
0
            case value_t::string:
14685
0
            {
14686
0
                if (JSON_UNLIKELY(not pos.m_it.primitive_iterator.is_begin()))
14687
0
                {
14688
0
                    JSON_THROW(invalid_iterator::create(205, "iterator out of range"));
14689
0
                }
14690
0
14691
0
                if (is_string())
14692
0
                {
14693
0
                    AllocatorType<string_t> alloc;
14694
0
                    std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
14695
0
                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
14696
0
                    m_value.string = nullptr;
14697
0
                }
14698
0
14699
0
                m_type = value_t::null;
14700
0
                assert_invariant();
14701
0
                break;
14702
0
            }
14703
0
14704
0
            case value_t::object:
14705
0
            {
14706
0
                result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
14707
0
                break;
14708
0
            }
14709
0
14710
0
            case value_t::array:
14711
0
            {
14712
0
                result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
14713
0
                break;
14714
0
            }
14715
0
14716
0
            default:
14717
0
                JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
14718
0
        }
14719
0
14720
0
        return result;
14721
0
    }
14722
14723
    /*!
14724
    @brief remove elements given an iterator range
14725
14726
    Removes the element specified by the range `[first; last)`. The iterator
14727
    @a first does not need to be dereferenceable if `first == last`: erasing
14728
    an empty range is a no-op.
14729
14730
    If called on a primitive type other than `null`, the resulting JSON value
14731
    will be `null`.
14732
14733
    @param[in] first iterator to the beginning of the range to remove
14734
    @param[in] last iterator past the end of the range to remove
14735
    @return Iterator following the last removed element. If the iterator @a
14736
    second refers to the last element, the `end()` iterator is returned.
14737
14738
    @tparam IteratorType an @ref iterator or @ref const_iterator
14739
14740
    @post Invalidates iterators and references at or after the point of the
14741
    erase, including the `end()` iterator.
14742
14743
    @throw type_error.307 if called on a `null` value; example: `"cannot use
14744
    erase() with null"`
14745
    @throw invalid_iterator.203 if called on iterators which does not belong
14746
    to the current JSON value; example: `"iterators do not fit current value"`
14747
    @throw invalid_iterator.204 if called on a primitive type with invalid
14748
    iterators (i.e., if `first != begin()` and `last != end()`); example:
14749
    `"iterators out of range"`
14750
14751
    @complexity The complexity depends on the type:
14752
    - objects: `log(size()) + std::distance(first, last)`
14753
    - arrays: linear in the distance between @a first and @a last, plus linear
14754
      in the distance between @a last and end of the container
14755
    - strings: linear in the length of the string
14756
    - other types: constant
14757
14758
    @liveexample{The example shows the result of `erase()` for different JSON
14759
    types.,erase__IteratorType_IteratorType}
14760
14761
    @sa @ref erase(IteratorType) -- removes the element at a given position
14762
    @sa @ref erase(const typename object_t::key_type&) -- removes the element
14763
    from an object at the given key
14764
    @sa @ref erase(const size_type) -- removes the element from an array at
14765
    the given index
14766
14767
    @since version 1.0.0
14768
    */
14769
    template<class IteratorType, typename std::enable_if<
14770
                 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
14771
                 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
14772
             = 0>
14773
    IteratorType erase(IteratorType first, IteratorType last)
14774
    {
14775
        // make sure iterator fits the current value
14776
        if (JSON_UNLIKELY(this != first.m_object or this != last.m_object))
14777
        {
14778
            JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value"));
14779
        }
14780
14781
        IteratorType result = end();
14782
14783
        switch (m_type)
14784
        {
14785
            case value_t::boolean:
14786
            case value_t::number_float:
14787
            case value_t::number_integer:
14788
            case value_t::number_unsigned:
14789
            case value_t::string:
14790
            {
14791
                if (JSON_LIKELY(not first.m_it.primitive_iterator.is_begin()
14792
                                or not last.m_it.primitive_iterator.is_end()))
14793
                {
14794
                    JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
14795
                }
14796
14797
                if (is_string())
14798
                {
14799
                    AllocatorType<string_t> alloc;
14800
                    std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
14801
                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
14802
                    m_value.string = nullptr;
14803
                }
14804
14805
                m_type = value_t::null;
14806
                assert_invariant();
14807
                break;
14808
            }
14809
14810
            case value_t::object:
14811
            {
14812
                result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
14813
                                              last.m_it.object_iterator);
14814
                break;
14815
            }
14816
14817
            case value_t::array:
14818
            {
14819
                result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
14820
                                             last.m_it.array_iterator);
14821
                break;
14822
            }
14823
14824
            default:
14825
                JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
14826
        }
14827
14828
        return result;
14829
    }
14830
14831
    /*!
14832
    @brief remove element from a JSON object given a key
14833
14834
    Removes elements from a JSON object with the key value @a key.
14835
14836
    @param[in] key value of the elements to remove
14837
14838
    @return Number of elements removed. If @a ObjectType is the default
14839
    `std::map` type, the return value will always be `0` (@a key was not
14840
    found) or `1` (@a key was found).
14841
14842
    @post References and iterators to the erased elements are invalidated.
14843
    Other references and iterators are not affected.
14844
14845
    @throw type_error.307 when called on a type other than JSON object;
14846
    example: `"cannot use erase() with null"`
14847
14848
    @complexity `log(size()) + count(key)`
14849
14850
    @liveexample{The example shows the effect of `erase()`.,erase__key_type}
14851
14852
    @sa @ref erase(IteratorType) -- removes the element at a given position
14853
    @sa @ref erase(IteratorType, IteratorType) -- removes the elements in
14854
    the given range
14855
    @sa @ref erase(const size_type) -- removes the element from an array at
14856
    the given index
14857
14858
    @since version 1.0.0
14859
    */
14860
    size_type erase(const typename object_t::key_type& key)
14861
    {
14862
        // this erase only works for objects
14863
        if (JSON_LIKELY(is_object()))
14864
        {
14865
            return m_value.object->erase(key);
14866
        }
14867
14868
        JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
14869
    }
14870
14871
    /*!
14872
    @brief remove element from a JSON array given an index
14873
14874
    Removes element from a JSON array at the index @a idx.
14875
14876
    @param[in] idx index of the element to remove
14877
14878
    @throw type_error.307 when called on a type other than JSON object;
14879
    example: `"cannot use erase() with null"`
14880
    @throw out_of_range.401 when `idx >= size()`; example: `"array index 17
14881
    is out of range"`
14882
14883
    @complexity Linear in distance between @a idx and the end of the container.
14884
14885
    @liveexample{The example shows the effect of `erase()`.,erase__size_type}
14886
14887
    @sa @ref erase(IteratorType) -- removes the element at a given position
14888
    @sa @ref erase(IteratorType, IteratorType) -- removes the elements in
14889
    the given range
14890
    @sa @ref erase(const typename object_t::key_type&) -- removes the element
14891
    from an object at the given key
14892
14893
    @since version 1.0.0
14894
    */
14895
    void erase(const size_type idx)
14896
    {
14897
        // this erase only works for arrays
14898
        if (JSON_LIKELY(is_array()))
14899
        {
14900
            if (JSON_UNLIKELY(idx >= size()))
14901
            {
14902
                JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
14903
            }
14904
14905
            m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
14906
        }
14907
        else
14908
        {
14909
            JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
14910
        }
14911
    }
14912
14913
    /// @}
14914
14915
14916
    ////////////
14917
    // lookup //
14918
    ////////////
14919
14920
    /// @name lookup
14921
    /// @{
14922
14923
    /*!
14924
    @brief find an element in a JSON object
14925
14926
    Finds an element in a JSON object with key equivalent to @a key. If the
14927
    element is not found or the JSON value is not an object, end() is
14928
    returned.
14929
14930
    @note This method always returns @ref end() when executed on a JSON type
14931
          that is not an object.
14932
14933
    @param[in] key key value of the element to search for.
14934
14935
    @return Iterator to an element with key equivalent to @a key. If no such
14936
    element is found or the JSON value is not an object, past-the-end (see
14937
    @ref end()) iterator is returned.
14938
14939
    @complexity Logarithmic in the size of the JSON object.
14940
14941
    @liveexample{The example shows how `find()` is used.,find__key_type}
14942
14943
    @since version 1.0.0
14944
    */
14945
    template<typename KeyT>
14946
    iterator find(KeyT&& key)
14947
15
    {
14948
15
        auto result = end();
14949
15
14950
15
        if (is_object())
14951
15
        {
14952
14
            result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
14953
14
        }
14954
15
14955
15
        return result;
14956
15
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE4findIRA15_KcEENS_6detail9iter_implISA_EEOT_
Line
Count
Source
14947
2
    {
14948
2
        auto result = end();
14949
2
14950
2
        if (is_object())
14951
2
        {
14952
2
            result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
14953
2
        }
14954
2
14955
2
        return result;
14956
2
    }
_ZN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEE4findIRA9_KcEENS_6detail9iter_implISA_EEOT_
Line
Count
Source
14947
13
    {
14948
13
        auto result = end();
14949
13
14950
13
        if (is_object())
14951
13
        {
14952
12
            result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
14953
12
        }
14954
13
14955
13
        return result;
14956
13
    }
14957
14958
    /*!
14959
    @brief find an element in a JSON object
14960
    @copydoc find(KeyT&&)
14961
    */
14962
    template<typename KeyT>
14963
    const_iterator find(KeyT&& key) const
14964
    {
14965
        auto result = cend();
14966
14967
        if (is_object())
14968
        {
14969
            result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
14970
        }
14971
14972
        return result;
14973
    }
14974
14975
    /*!
14976
    @brief returns the number of occurrences of a key in a JSON object
14977
14978
    Returns the number of elements with key @a key. If ObjectType is the
14979
    default `std::map` type, the return value will always be `0` (@a key was
14980
    not found) or `1` (@a key was found).
14981
14982
    @note This method always returns `0` when executed on a JSON type that is
14983
          not an object.
14984
14985
    @param[in] key key value of the element to count
14986
14987
    @return Number of elements with key @a key. If the JSON value is not an
14988
    object, the return value will be `0`.
14989
14990
    @complexity Logarithmic in the size of the JSON object.
14991
14992
    @liveexample{The example shows how `count()` is used.,count}
14993
14994
    @since version 1.0.0
14995
    */
14996
    template<typename KeyT>
14997
    size_type count(KeyT&& key) const
14998
    {
14999
        // return 0 for all nonobject types
15000
        return is_object() ? m_value.object->count(std::forward<KeyT>(key)) : 0;
15001
    }
15002
15003
    /// @}
15004
15005
15006
    ///////////////
15007
    // iterators //
15008
    ///////////////
15009
15010
    /// @name iterators
15011
    /// @{
15012
15013
    /*!
15014
    @brief returns an iterator to the first element
15015
15016
    Returns an iterator to the first element.
15017
15018
    @image html range-begin-end.svg "Illustration from cppreference.com"
15019
15020
    @return iterator to the first element
15021
15022
    @complexity Constant.
15023
15024
    @requirement This function helps `basic_json` satisfying the
15025
    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
15026
    requirements:
15027
    - The complexity is constant.
15028
15029
    @liveexample{The following code shows an example for `begin()`.,begin}
15030
15031
    @sa @ref cbegin() -- returns a const iterator to the beginning
15032
    @sa @ref end() -- returns an iterator to the end
15033
    @sa @ref cend() -- returns a const iterator to the end
15034
15035
    @since version 1.0.0
15036
    */
15037
    iterator begin() noexcept
15038
590
    {
15039
590
        iterator result(this);
15040
590
        result.set_begin();
15041
590
        return result;
15042
590
    }
15043
15044
    /*!
15045
    @copydoc basic_json::cbegin()
15046
    */
15047
    const_iterator begin() const noexcept
15048
    {
15049
        return cbegin();
15050
    }
15051
15052
    /*!
15053
    @brief returns a const iterator to the first element
15054
15055
    Returns a const iterator to the first element.
15056
15057
    @image html range-begin-end.svg "Illustration from cppreference.com"
15058
15059
    @return const iterator to the first element
15060
15061
    @complexity Constant.
15062
15063
    @requirement This function helps `basic_json` satisfying the
15064
    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
15065
    requirements:
15066
    - The complexity is constant.
15067
    - Has the semantics of `const_cast<const basic_json&>(*this).begin()`.
15068
15069
    @liveexample{The following code shows an example for `cbegin()`.,cbegin}
15070
15071
    @sa @ref begin() -- returns an iterator to the beginning
15072
    @sa @ref end() -- returns an iterator to the end
15073
    @sa @ref cend() -- returns a const iterator to the end
15074
15075
    @since version 1.0.0
15076
    */
15077
    const_iterator cbegin() const noexcept
15078
    {
15079
        const_iterator result(this);
15080
        result.set_begin();
15081
        return result;
15082
    }
15083
15084
    /*!
15085
    @brief returns an iterator to one past the last element
15086
15087
    Returns an iterator to one past the last element.
15088
15089
    @image html range-begin-end.svg "Illustration from cppreference.com"
15090
15091
    @return iterator one past the last element
15092
15093
    @complexity Constant.
15094
15095
    @requirement This function helps `basic_json` satisfying the
15096
    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
15097
    requirements:
15098
    - The complexity is constant.
15099
15100
    @liveexample{The following code shows an example for `end()`.,end}
15101
15102
    @sa @ref cend() -- returns a const iterator to the end
15103
    @sa @ref begin() -- returns an iterator to the beginning
15104
    @sa @ref cbegin() -- returns a const iterator to the beginning
15105
15106
    @since version 1.0.0
15107
    */
15108
    iterator end() noexcept
15109
1.98k
    {
15110
1.98k
        iterator result(this);
15111
1.98k
        result.set_end();
15112
1.98k
        return result;
15113
1.98k
    }
15114
15115
    /*!
15116
    @copydoc basic_json::cend()
15117
    */
15118
    const_iterator end() const noexcept
15119
    {
15120
        return cend();
15121
    }
15122
15123
    /*!
15124
    @brief returns a const iterator to one past the last element
15125
15126
    Returns a const iterator to one past the last element.
15127
15128
    @image html range-begin-end.svg "Illustration from cppreference.com"
15129
15130
    @return const iterator one past the last element
15131
15132
    @complexity Constant.
15133
15134
    @requirement This function helps `basic_json` satisfying the
15135
    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
15136
    requirements:
15137
    - The complexity is constant.
15138
    - Has the semantics of `const_cast<const basic_json&>(*this).end()`.
15139
15140
    @liveexample{The following code shows an example for `cend()`.,cend}
15141
15142
    @sa @ref end() -- returns an iterator to the end
15143
    @sa @ref begin() -- returns an iterator to the beginning
15144
    @sa @ref cbegin() -- returns a const iterator to the beginning
15145
15146
    @since version 1.0.0
15147
    */
15148
    const_iterator cend() const noexcept
15149
    {
15150
        const_iterator result(this);
15151
        result.set_end();
15152
        return result;
15153
    }
15154
15155
    /*!
15156
    @brief returns an iterator to the reverse-beginning
15157
15158
    Returns an iterator to the reverse-beginning; that is, the last element.
15159
15160
    @image html range-rbegin-rend.svg "Illustration from cppreference.com"
15161
15162
    @complexity Constant.
15163
15164
    @requirement This function helps `basic_json` satisfying the
15165
    [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
15166
    requirements:
15167
    - The complexity is constant.
15168
    - Has the semantics of `reverse_iterator(end())`.
15169
15170
    @liveexample{The following code shows an example for `rbegin()`.,rbegin}
15171
15172
    @sa @ref crbegin() -- returns a const reverse iterator to the beginning
15173
    @sa @ref rend() -- returns a reverse iterator to the end
15174
    @sa @ref crend() -- returns a const reverse iterator to the end
15175
15176
    @since version 1.0.0
15177
    */
15178
    reverse_iterator rbegin() noexcept
15179
    {
15180
        return reverse_iterator(end());
15181
    }
15182
15183
    /*!
15184
    @copydoc basic_json::crbegin()
15185
    */
15186
    const_reverse_iterator rbegin() const noexcept
15187
    {
15188
        return crbegin();
15189
    }
15190
15191
    /*!
15192
    @brief returns an iterator to the reverse-end
15193
15194
    Returns an iterator to the reverse-end; that is, one before the first
15195
    element.
15196
15197
    @image html range-rbegin-rend.svg "Illustration from cppreference.com"
15198
15199
    @complexity Constant.
15200
15201
    @requirement This function helps `basic_json` satisfying the
15202
    [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
15203
    requirements:
15204
    - The complexity is constant.
15205
    - Has the semantics of `reverse_iterator(begin())`.
15206
15207
    @liveexample{The following code shows an example for `rend()`.,rend}
15208
15209
    @sa @ref crend() -- returns a const reverse iterator to the end
15210
    @sa @ref rbegin() -- returns a reverse iterator to the beginning
15211
    @sa @ref crbegin() -- returns a const reverse iterator to the beginning
15212
15213
    @since version 1.0.0
15214
    */
15215
    reverse_iterator rend() noexcept
15216
    {
15217
        return reverse_iterator(begin());
15218
    }
15219
15220
    /*!
15221
    @copydoc basic_json::crend()
15222
    */
15223
    const_reverse_iterator rend() const noexcept
15224
    {
15225
        return crend();
15226
    }
15227
15228
    /*!
15229
    @brief returns a const reverse iterator to the last element
15230
15231
    Returns a const iterator to the reverse-beginning; that is, the last
15232
    element.
15233
15234
    @image html range-rbegin-rend.svg "Illustration from cppreference.com"
15235
15236
    @complexity Constant.
15237
15238
    @requirement This function helps `basic_json` satisfying the
15239
    [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
15240
    requirements:
15241
    - The complexity is constant.
15242
    - Has the semantics of `const_cast<const basic_json&>(*this).rbegin()`.
15243
15244
    @liveexample{The following code shows an example for `crbegin()`.,crbegin}
15245
15246
    @sa @ref rbegin() -- returns a reverse iterator to the beginning
15247
    @sa @ref rend() -- returns a reverse iterator to the end
15248
    @sa @ref crend() -- returns a const reverse iterator to the end
15249
15250
    @since version 1.0.0
15251
    */
15252
    const_reverse_iterator crbegin() const noexcept
15253
    {
15254
        return const_reverse_iterator(cend());
15255
    }
15256
15257
    /*!
15258
    @brief returns a const reverse iterator to one before the first
15259
15260
    Returns a const reverse iterator to the reverse-end; that is, one before
15261
    the first element.
15262
15263
    @image html range-rbegin-rend.svg "Illustration from cppreference.com"
15264
15265
    @complexity Constant.
15266
15267
    @requirement This function helps `basic_json` satisfying the
15268
    [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
15269
    requirements:
15270
    - The complexity is constant.
15271
    - Has the semantics of `const_cast<const basic_json&>(*this).rend()`.
15272
15273
    @liveexample{The following code shows an example for `crend()`.,crend}
15274
15275
    @sa @ref rend() -- returns a reverse iterator to the end
15276
    @sa @ref rbegin() -- returns a reverse iterator to the beginning
15277
    @sa @ref crbegin() -- returns a const reverse iterator to the beginning
15278
15279
    @since version 1.0.0
15280
    */
15281
    const_reverse_iterator crend() const noexcept
15282
    {
15283
        return const_reverse_iterator(cbegin());
15284
    }
15285
15286
  public:
15287
    /*!
15288
    @brief wrapper to access iterator member functions in range-based for
15289
15290
    This function allows to access @ref iterator::key() and @ref
15291
    iterator::value() during range-based for loops. In these loops, a
15292
    reference to the JSON values is returned, so there is no access to the
15293
    underlying iterator.
15294
15295
    For loop without iterator_wrapper:
15296
15297
    @code{cpp}
15298
    for (auto it = j_object.begin(); it != j_object.end(); ++it)
15299
    {
15300
        std::cout << "key: " << it.key() << ", value:" << it.value() << '\n';
15301
    }
15302
    @endcode
15303
15304
    Range-based for loop without iterator proxy:
15305
15306
    @code{cpp}
15307
    for (auto it : j_object)
15308
    {
15309
        // "it" is of type json::reference and has no key() member
15310
        std::cout << "value: " << it << '\n';
15311
    }
15312
    @endcode
15313
15314
    Range-based for loop with iterator proxy:
15315
15316
    @code{cpp}
15317
    for (auto it : json::iterator_wrapper(j_object))
15318
    {
15319
        std::cout << "key: " << it.key() << ", value:" << it.value() << '\n';
15320
    }
15321
    @endcode
15322
15323
    @note When iterating over an array, `key()` will return the index of the
15324
          element as string (see example).
15325
15326
    @param[in] ref  reference to a JSON value
15327
    @return iteration proxy object wrapping @a ref with an interface to use in
15328
            range-based for loops
15329
15330
    @liveexample{The following code shows how the wrapper is used,iterator_wrapper}
15331
15332
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
15333
    changes in the JSON value.
15334
15335
    @complexity Constant.
15336
15337
    @note The name of this function is not yet final and may change in the
15338
    future.
15339
15340
    @deprecated This stream operator is deprecated and will be removed in
15341
                future 4.0.0 of the library. Please use @ref items() instead;
15342
                that is, replace `json::iterator_wrapper(j)` with `j.items()`.
15343
    */
15344
    JSON_DEPRECATED
15345
    static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
15346
    {
15347
        return ref.items();
15348
    }
15349
15350
    /*!
15351
    @copydoc iterator_wrapper(reference)
15352
    */
15353
    JSON_DEPRECATED
15354
    static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
15355
    {
15356
        return ref.items();
15357
    }
15358
15359
    /*!
15360
    @brief helper to access iterator member functions in range-based for
15361
15362
    This function allows to access @ref iterator::key() and @ref
15363
    iterator::value() during range-based for loops. In these loops, a
15364
    reference to the JSON values is returned, so there is no access to the
15365
    underlying iterator.
15366
15367
    For loop without `items()` function:
15368
15369
    @code{cpp}
15370
    for (auto it = j_object.begin(); it != j_object.end(); ++it)
15371
    {
15372
        std::cout << "key: " << it.key() << ", value:" << it.value() << '\n';
15373
    }
15374
    @endcode
15375
15376
    Range-based for loop without `items()` function:
15377
15378
    @code{cpp}
15379
    for (auto it : j_object)
15380
    {
15381
        // "it" is of type json::reference and has no key() member
15382
        std::cout << "value: " << it << '\n';
15383
    }
15384
    @endcode
15385
15386
    Range-based for loop with `items()` function:
15387
15388
    @code{cpp}
15389
    for (auto it : j_object.items())
15390
    {
15391
        std::cout << "key: " << it.key() << ", value:" << it.value() << '\n';
15392
    }
15393
    @endcode
15394
15395
    @note When iterating over an array, `key()` will return the index of the
15396
          element as string (see example). For primitive types (e.g., numbers),
15397
          `key()` returns an empty string.
15398
15399
    @return iteration proxy object wrapping @a ref with an interface to use in
15400
            range-based for loops
15401
15402
    @liveexample{The following code shows how the function is used.,items}
15403
15404
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
15405
    changes in the JSON value.
15406
15407
    @complexity Constant.
15408
15409
    @since version 3.1.0.
15410
    */
15411
    iteration_proxy<iterator> items() noexcept
15412
    {
15413
        return iteration_proxy<iterator>(*this);
15414
    }
15415
15416
    /*!
15417
    @copydoc items()
15418
    */
15419
    iteration_proxy<const_iterator> items() const noexcept
15420
    {
15421
        return iteration_proxy<const_iterator>(*this);
15422
    }
15423
15424
    /// @}
15425
15426
15427
    //////////////
15428
    // capacity //
15429
    //////////////
15430
15431
    /// @name capacity
15432
    /// @{
15433
15434
    /*!
15435
    @brief checks whether the container is empty.
15436
15437
    Checks if a JSON value has no elements (i.e. whether its @ref size is `0`).
15438
15439
    @return The return value depends on the different types and is
15440
            defined as follows:
15441
            Value type  | return value
15442
            ----------- | -------------
15443
            null        | `true`
15444
            boolean     | `false`
15445
            string      | `false`
15446
            number      | `false`
15447
            object      | result of function `object_t::empty()`
15448
            array       | result of function `array_t::empty()`
15449
15450
    @liveexample{The following code uses `empty()` to check if a JSON
15451
    object contains any elements.,empty}
15452
15453
    @complexity Constant, as long as @ref array_t and @ref object_t satisfy
15454
    the Container concept; that is, their `empty()` functions have constant
15455
    complexity.
15456
15457
    @iterators No changes.
15458
15459
    @exceptionsafety No-throw guarantee: this function never throws exceptions.
15460
15461
    @note This function does not return whether a string stored as JSON value
15462
    is empty - it returns whether the JSON container itself is empty which is
15463
    false in the case of a string.
15464
15465
    @requirement This function helps `basic_json` satisfying the
15466
    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
15467
    requirements:
15468
    - The complexity is constant.
15469
    - Has the semantics of `begin() == end()`.
15470
15471
    @sa @ref size() -- returns the number of elements
15472
15473
    @since version 1.0.0
15474
    */
15475
    bool empty() const noexcept
15476
    {
15477
        switch (m_type)
15478
        {
15479
            case value_t::null:
15480
            {
15481
                // null values are empty
15482
                return true;
15483
            }
15484
15485
            case value_t::array:
15486
            {
15487
                // delegate call to array_t::empty()
15488
                return m_value.array->empty();
15489
            }
15490
15491
            case value_t::object:
15492
            {
15493
                // delegate call to object_t::empty()
15494
                return m_value.object->empty();
15495
            }
15496
15497
            default:
15498
            {
15499
                // all other types are nonempty
15500
                return false;
15501
            }
15502
        }
15503
    }
15504
15505
    /*!
15506
    @brief returns the number of elements
15507
15508
    Returns the number of elements in a JSON value.
15509
15510
    @return The return value depends on the different types and is
15511
            defined as follows:
15512
            Value type  | return value
15513
            ----------- | -------------
15514
            null        | `0`
15515
            boolean     | `1`
15516
            string      | `1`
15517
            number      | `1`
15518
            object      | result of function object_t::size()
15519
            array       | result of function array_t::size()
15520
15521
    @liveexample{The following code calls `size()` on the different value
15522
    types.,size}
15523
15524
    @complexity Constant, as long as @ref array_t and @ref object_t satisfy
15525
    the Container concept; that is, their size() functions have constant
15526
    complexity.
15527
15528
    @iterators No changes.
15529
15530
    @exceptionsafety No-throw guarantee: this function never throws exceptions.
15531
15532
    @note This function does not return the length of a string stored as JSON
15533
    value - it returns the number of elements in the JSON value which is 1 in
15534
    the case of a string.
15535
15536
    @requirement This function helps `basic_json` satisfying the
15537
    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
15538
    requirements:
15539
    - The complexity is constant.
15540
    - Has the semantics of `std::distance(begin(), end())`.
15541
15542
    @sa @ref empty() -- checks whether the container is empty
15543
    @sa @ref max_size() -- returns the maximal number of elements
15544
15545
    @since version 1.0.0
15546
    */
15547
    size_type size() const noexcept
15548
33
    {
15549
33
        switch (m_type)
15550
0
        {
15551
13
            case value_t::null:
15552
13
            {
15553
13
                // null values are empty
15554
13
                return 0;
15555
13
            }
15556
13
15557
20
            case value_t::array:
15558
20
            {
15559
20
                // delegate call to array_t::size()
15560
20
                return m_value.array->size();
15561
13
            }
15562
13
15563
13
            case value_t::object:
15564
0
            {
15565
0
                // delegate call to object_t::size()
15566
0
                return m_value.object->size();
15567
13
            }
15568
13
15569
13
            default:
15570
0
            {
15571
0
                // all other types have size 1
15572
0
                return 1;
15573
13
            }
15574
0
        }
15575
33
    }
15576
15577
    /*!
15578
    @brief returns the maximum possible number of elements
15579
15580
    Returns the maximum number of elements a JSON value is able to hold due to
15581
    system or library implementation limitations, i.e. `std::distance(begin(),
15582
    end())` for the JSON value.
15583
15584
    @return The return value depends on the different types and is
15585
            defined as follows:
15586
            Value type  | return value
15587
            ----------- | -------------
15588
            null        | `0` (same as `size()`)
15589
            boolean     | `1` (same as `size()`)
15590
            string      | `1` (same as `size()`)
15591
            number      | `1` (same as `size()`)
15592
            object      | result of function `object_t::max_size()`
15593
            array       | result of function `array_t::max_size()`
15594
15595
    @liveexample{The following code calls `max_size()` on the different value
15596
    types. Note the output is implementation specific.,max_size}
15597
15598
    @complexity Constant, as long as @ref array_t and @ref object_t satisfy
15599
    the Container concept; that is, their `max_size()` functions have constant
15600
    complexity.
15601
15602
    @iterators No changes.
15603
15604
    @exceptionsafety No-throw guarantee: this function never throws exceptions.
15605
15606
    @requirement This function helps `basic_json` satisfying the
15607
    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
15608
    requirements:
15609
    - The complexity is constant.
15610
    - Has the semantics of returning `b.size()` where `b` is the largest
15611
      possible JSON value.
15612
15613
    @sa @ref size() -- returns the number of elements
15614
15615
    @since version 1.0.0
15616
    */
15617
    size_type max_size() const noexcept
15618
0
    {
15619
0
        switch (m_type)
15620
0
        {
15621
0
            case value_t::array:
15622
0
            {
15623
0
                // delegate call to array_t::max_size()
15624
0
                return m_value.array->max_size();
15625
0
            }
15626
0
15627
0
            case value_t::object:
15628
0
            {
15629
0
                // delegate call to object_t::max_size()
15630
0
                return m_value.object->max_size();
15631
0
            }
15632
0
15633
0
            default:
15634
0
            {
15635
0
                // all other types have max_size() == size()
15636
0
                return size();
15637
0
            }
15638
0
        }
15639
0
    }
15640
15641
    /// @}
15642
15643
15644
    ///////////////
15645
    // modifiers //
15646
    ///////////////
15647
15648
    /// @name modifiers
15649
    /// @{
15650
15651
    /*!
15652
    @brief clears the contents
15653
15654
    Clears the content of a JSON value and resets it to the default value as
15655
    if @ref basic_json(value_t) would have been called with the current value
15656
    type from @ref type():
15657
15658
    Value type  | initial value
15659
    ----------- | -------------
15660
    null        | `null`
15661
    boolean     | `false`
15662
    string      | `""`
15663
    number      | `0`
15664
    object      | `{}`
15665
    array       | `[]`
15666
15667
    @post Has the same effect as calling
15668
    @code {.cpp}
15669
    *this = basic_json(type());
15670
    @endcode
15671
15672
    @liveexample{The example below shows the effect of `clear()` to different
15673
    JSON types.,clear}
15674
15675
    @complexity Linear in the size of the JSON value.
15676
15677
    @iterators All iterators, pointers and references related to this container
15678
               are invalidated.
15679
15680
    @exceptionsafety No-throw guarantee: this function never throws exceptions.
15681
15682
    @sa @ref basic_json(value_t) -- constructor that creates an object with the
15683
        same value than calling `clear()`
15684
15685
    @since version 1.0.0
15686
    */
15687
    void clear() noexcept
15688
    {
15689
        switch (m_type)
15690
        {
15691
            case value_t::number_integer:
15692
            {
15693
                m_value.number_integer = 0;
15694
                break;
15695
            }
15696
15697
            case value_t::number_unsigned:
15698
            {
15699
                m_value.number_unsigned = 0;
15700
                break;
15701
            }
15702
15703
            case value_t::number_float:
15704
            {
15705
                m_value.number_float = 0.0;
15706
                break;
15707
            }
15708
15709
            case value_t::boolean:
15710
            {
15711
                m_value.boolean = false;
15712
                break;
15713
            }
15714
15715
            case value_t::string:
15716
            {
15717
                m_value.string->clear();
15718
                break;
15719
            }
15720
15721
            case value_t::array:
15722
            {
15723
                m_value.array->clear();
15724
                break;
15725
            }
15726
15727
            case value_t::object:
15728
            {
15729
                m_value.object->clear();
15730
                break;
15731
            }
15732
15733
            default:
15734
                break;
15735
        }
15736
    }
15737
15738
    /*!
15739
    @brief add an object to an array
15740
15741
    Appends the given element @a val to the end of the JSON value. If the
15742
    function is called on a JSON null value, an empty array is created before
15743
    appending @a val.
15744
15745
    @param[in] val the value to add to the JSON array
15746
15747
    @throw type_error.308 when called on a type other than JSON array or
15748
    null; example: `"cannot use push_back() with number"`
15749
15750
    @complexity Amortized constant.
15751
15752
    @liveexample{The example shows how `push_back()` and `+=` can be used to
15753
    add elements to a JSON array. Note how the `null` value was silently
15754
    converted to a JSON array.,push_back}
15755
15756
    @since version 1.0.0
15757
    */
15758
    void push_back(basic_json&& val)
15759
    {
15760
        // push_back only works for null objects or arrays
15761
        if (JSON_UNLIKELY(not(is_null() or is_array())))
15762
        {
15763
            JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
15764
        }
15765
15766
        // transform null object into an array
15767
        if (is_null())
15768
        {
15769
            m_type = value_t::array;
15770
            m_value = value_t::array;
15771
            assert_invariant();
15772
        }
15773
15774
        // add element to array (move semantics)
15775
        m_value.array->push_back(std::move(val));
15776
        // invalidate object
15777
        val.m_type = value_t::null;
15778
    }
15779
15780
    /*!
15781
    @brief add an object to an array
15782
    @copydoc push_back(basic_json&&)
15783
    */
15784
    reference operator+=(basic_json&& val)
15785
    {
15786
        push_back(std::move(val));
15787
        return *this;
15788
    }
15789
15790
    /*!
15791
    @brief add an object to an array
15792
    @copydoc push_back(basic_json&&)
15793
    */
15794
    void push_back(const basic_json& val)
15795
    {
15796
        // push_back only works for null objects or arrays
15797
        if (JSON_UNLIKELY(not(is_null() or is_array())))
15798
        {
15799
            JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
15800
        }
15801
15802
        // transform null object into an array
15803
        if (is_null())
15804
        {
15805
            m_type = value_t::array;
15806
            m_value = value_t::array;
15807
            assert_invariant();
15808
        }
15809
15810
        // add element to array
15811
        m_value.array->push_back(val);
15812
    }
15813
15814
    /*!
15815
    @brief add an object to an array
15816
    @copydoc push_back(basic_json&&)
15817
    */
15818
    reference operator+=(const basic_json& val)
15819
    {
15820
        push_back(val);
15821
        return *this;
15822
    }
15823
15824
    /*!
15825
    @brief add an object to an object
15826
15827
    Inserts the given element @a val to the JSON object. If the function is
15828
    called on a JSON null value, an empty object is created before inserting
15829
    @a val.
15830
15831
    @param[in] val the value to add to the JSON object
15832
15833
    @throw type_error.308 when called on a type other than JSON object or
15834
    null; example: `"cannot use push_back() with number"`
15835
15836
    @complexity Logarithmic in the size of the container, O(log(`size()`)).
15837
15838
    @liveexample{The example shows how `push_back()` and `+=` can be used to
15839
    add elements to a JSON object. Note how the `null` value was silently
15840
    converted to a JSON object.,push_back__object_t__value}
15841
15842
    @since version 1.0.0
15843
    */
15844
    void push_back(const typename object_t::value_type& val)
15845
    {
15846
        // push_back only works for null objects or objects
15847
        if (JSON_UNLIKELY(not(is_null() or is_object())))
15848
        {
15849
            JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
15850
        }
15851
15852
        // transform null object into an object
15853
        if (is_null())
15854
        {
15855
            m_type = value_t::object;
15856
            m_value = value_t::object;
15857
            assert_invariant();
15858
        }
15859
15860
        // add element to array
15861
        m_value.object->insert(val);
15862
    }
15863
15864
    /*!
15865
    @brief add an object to an object
15866
    @copydoc push_back(const typename object_t::value_type&)
15867
    */
15868
    reference operator+=(const typename object_t::value_type& val)
15869
    {
15870
        push_back(val);
15871
        return *this;
15872
    }
15873
15874
    /*!
15875
    @brief add an object to an object
15876
15877
    This function allows to use `push_back` with an initializer list. In case
15878
15879
    1. the current value is an object,
15880
    2. the initializer list @a init contains only two elements, and
15881
    3. the first element of @a init is a string,
15882
15883
    @a init is converted into an object element and added using
15884
    @ref push_back(const typename object_t::value_type&). Otherwise, @a init
15885
    is converted to a JSON value and added using @ref push_back(basic_json&&).
15886
15887
    @param[in] init  an initializer list
15888
15889
    @complexity Linear in the size of the initializer list @a init.
15890
15891
    @note This function is required to resolve an ambiguous overload error,
15892
          because pairs like `{"key", "value"}` can be both interpreted as
15893
          `object_t::value_type` or `std::initializer_list<basic_json>`, see
15894
          https://github.com/nlohmann/json/issues/235 for more information.
15895
15896
    @liveexample{The example shows how initializer lists are treated as
15897
    objects when possible.,push_back__initializer_list}
15898
    */
15899
    void push_back(initializer_list_t init)
15900
    {
15901
        if (is_object() and init.size() == 2 and (*init.begin())->is_string())
15902
        {
15903
            basic_json&& key = init.begin()->moved_or_copied();
15904
            push_back(typename object_t::value_type(
15905
                          std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
15906
        }
15907
        else
15908
        {
15909
            push_back(basic_json(init));
15910
        }
15911
    }
15912
15913
    /*!
15914
    @brief add an object to an object
15915
    @copydoc push_back(initializer_list_t)
15916
    */
15917
    reference operator+=(initializer_list_t init)
15918
    {
15919
        push_back(init);
15920
        return *this;
15921
    }
15922
15923
    /*!
15924
    @brief add an object to an array
15925
15926
    Creates a JSON value from the passed parameters @a args to the end of the
15927
    JSON value. If the function is called on a JSON null value, an empty array
15928
    is created before appending the value created from @a args.
15929
15930
    @param[in] args arguments to forward to a constructor of @ref basic_json
15931
    @tparam Args compatible types to create a @ref basic_json object
15932
15933
    @throw type_error.311 when called on a type other than JSON array or
15934
    null; example: `"cannot use emplace_back() with number"`
15935
15936
    @complexity Amortized constant.
15937
15938
    @liveexample{The example shows how `push_back()` can be used to add
15939
    elements to a JSON array. Note how the `null` value was silently converted
15940
    to a JSON array.,emplace_back}
15941
15942
    @since version 2.0.8
15943
    */
15944
    template<class... Args>
15945
    void emplace_back(Args&& ... args)
15946
    {
15947
        // emplace_back only works for null objects or arrays
15948
        if (JSON_UNLIKELY(not(is_null() or is_array())))
15949
        {
15950
            JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name())));
15951
        }
15952
15953
        // transform null object into an array
15954
        if (is_null())
15955
        {
15956
            m_type = value_t::array;
15957
            m_value = value_t::array;
15958
            assert_invariant();
15959
        }
15960
15961
        // add element to array (perfect forwarding)
15962
        m_value.array->emplace_back(std::forward<Args>(args)...);
15963
    }
15964
15965
    /*!
15966
    @brief add an object to an object if key does not exist
15967
15968
    Inserts a new element into a JSON object constructed in-place with the
15969
    given @a args if there is no element with the key in the container. If the
15970
    function is called on a JSON null value, an empty object is created before
15971
    appending the value created from @a args.
15972
15973
    @param[in] args arguments to forward to a constructor of @ref basic_json
15974
    @tparam Args compatible types to create a @ref basic_json object
15975
15976
    @return a pair consisting of an iterator to the inserted element, or the
15977
            already-existing element if no insertion happened, and a bool
15978
            denoting whether the insertion took place.
15979
15980
    @throw type_error.311 when called on a type other than JSON object or
15981
    null; example: `"cannot use emplace() with number"`
15982
15983
    @complexity Logarithmic in the size of the container, O(log(`size()`)).
15984
15985
    @liveexample{The example shows how `emplace()` can be used to add elements
15986
    to a JSON object. Note how the `null` value was silently converted to a
15987
    JSON object. Further note how no value is added if there was already one
15988
    value stored with the same key.,emplace}
15989
15990
    @since version 2.0.8
15991
    */
15992
    template<class... Args>
15993
    std::pair<iterator, bool> emplace(Args&& ... args)
15994
    {
15995
        // emplace only works for null objects or arrays
15996
        if (JSON_UNLIKELY(not(is_null() or is_object())))
15997
        {
15998
            JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name())));
15999
        }
16000
16001
        // transform null object into an object
16002
        if (is_null())
16003
        {
16004
            m_type = value_t::object;
16005
            m_value = value_t::object;
16006
            assert_invariant();
16007
        }
16008
16009
        // add element to array (perfect forwarding)
16010
        auto res = m_value.object->emplace(std::forward<Args>(args)...);
16011
        // create result iterator and set iterator to the result of emplace
16012
        auto it = begin();
16013
        it.m_it.object_iterator = res.first;
16014
16015
        // return pair of iterator and boolean
16016
        return {it, res.second};
16017
    }
16018
16019
    /*!
16020
    @brief inserts element
16021
16022
    Inserts element @a val before iterator @a pos.
16023
16024
    @param[in] pos iterator before which the content will be inserted; may be
16025
    the end() iterator
16026
    @param[in] val element to insert
16027
    @return iterator pointing to the inserted @a val.
16028
16029
    @throw type_error.309 if called on JSON values other than arrays;
16030
    example: `"cannot use insert() with string"`
16031
    @throw invalid_iterator.202 if @a pos is not an iterator of *this;
16032
    example: `"iterator does not fit current value"`
16033
16034
    @complexity Constant plus linear in the distance between @a pos and end of
16035
    the container.
16036
16037
    @liveexample{The example shows how `insert()` is used.,insert}
16038
16039
    @since version 1.0.0
16040
    */
16041
    iterator insert(const_iterator pos, const basic_json& val)
16042
    {
16043
        // insert only works for arrays
16044
        if (JSON_LIKELY(is_array()))
16045
        {
16046
            // check if iterator pos fits to this JSON value
16047
            if (JSON_UNLIKELY(pos.m_object != this))
16048
            {
16049
                JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
16050
            }
16051
16052
            // insert to array and return iterator
16053
            iterator result(this);
16054
            result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
16055
            return result;
16056
        }
16057
16058
        JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
16059
    }
16060
16061
    /*!
16062
    @brief inserts element
16063
    @copydoc insert(const_iterator, const basic_json&)
16064
    */
16065
    iterator insert(const_iterator pos, basic_json&& val)
16066
    {
16067
        return insert(pos, val);
16068
    }
16069
16070
    /*!
16071
    @brief inserts elements
16072
16073
    Inserts @a cnt copies of @a val before iterator @a pos.
16074
16075
    @param[in] pos iterator before which the content will be inserted; may be
16076
    the end() iterator
16077
    @param[in] cnt number of copies of @a val to insert
16078
    @param[in] val element to insert
16079
    @return iterator pointing to the first element inserted, or @a pos if
16080
    `cnt==0`
16081
16082
    @throw type_error.309 if called on JSON values other than arrays; example:
16083
    `"cannot use insert() with string"`
16084
    @throw invalid_iterator.202 if @a pos is not an iterator of *this;
16085
    example: `"iterator does not fit current value"`
16086
16087
    @complexity Linear in @a cnt plus linear in the distance between @a pos
16088
    and end of the container.
16089
16090
    @liveexample{The example shows how `insert()` is used.,insert__count}
16091
16092
    @since version 1.0.0
16093
    */
16094
    iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
16095
    {
16096
        // insert only works for arrays
16097
        if (JSON_LIKELY(is_array()))
16098
        {
16099
            // check if iterator pos fits to this JSON value
16100
            if (JSON_UNLIKELY(pos.m_object != this))
16101
            {
16102
                JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
16103
            }
16104
16105
            // insert to array and return iterator
16106
            iterator result(this);
16107
            result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
16108
            return result;
16109
        }
16110
16111
        JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
16112
    }
16113
16114
    /*!
16115
    @brief inserts elements
16116
16117
    Inserts elements from range `[first, last)` before iterator @a pos.
16118
16119
    @param[in] pos iterator before which the content will be inserted; may be
16120
    the end() iterator
16121
    @param[in] first begin of the range of elements to insert
16122
    @param[in] last end of the range of elements to insert
16123
16124
    @throw type_error.309 if called on JSON values other than arrays; example:
16125
    `"cannot use insert() with string"`
16126
    @throw invalid_iterator.202 if @a pos is not an iterator of *this;
16127
    example: `"iterator does not fit current value"`
16128
    @throw invalid_iterator.210 if @a first and @a last do not belong to the
16129
    same JSON value; example: `"iterators do not fit"`
16130
    @throw invalid_iterator.211 if @a first or @a last are iterators into
16131
    container for which insert is called; example: `"passed iterators may not
16132
    belong to container"`
16133
16134
    @return iterator pointing to the first element inserted, or @a pos if
16135
    `first==last`
16136
16137
    @complexity Linear in `std::distance(first, last)` plus linear in the
16138
    distance between @a pos and end of the container.
16139
16140
    @liveexample{The example shows how `insert()` is used.,insert__range}
16141
16142
    @since version 1.0.0
16143
    */
16144
    iterator insert(const_iterator pos, const_iterator first, const_iterator last)
16145
    {
16146
        // insert only works for arrays
16147
        if (JSON_UNLIKELY(not is_array()))
16148
        {
16149
            JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
16150
        }
16151
16152
        // check if iterator pos fits to this JSON value
16153
        if (JSON_UNLIKELY(pos.m_object != this))
16154
        {
16155
            JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
16156
        }
16157
16158
        // check if range iterators belong to the same JSON object
16159
        if (JSON_UNLIKELY(first.m_object != last.m_object))
16160
        {
16161
            JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
16162
        }
16163
16164
        if (JSON_UNLIKELY(first.m_object == this))
16165
        {
16166
            JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container"));
16167
        }
16168
16169
        // insert to array and return iterator
16170
        iterator result(this);
16171
        result.m_it.array_iterator = m_value.array->insert(
16172
                                         pos.m_it.array_iterator,
16173
                                         first.m_it.array_iterator,
16174
                                         last.m_it.array_iterator);
16175
        return result;
16176
    }
16177
16178
    /*!
16179
    @brief inserts elements
16180
16181
    Inserts elements from initializer list @a ilist before iterator @a pos.
16182
16183
    @param[in] pos iterator before which the content will be inserted; may be
16184
    the end() iterator
16185
    @param[in] ilist initializer list to insert the values from
16186
16187
    @throw type_error.309 if called on JSON values other than arrays; example:
16188
    `"cannot use insert() with string"`
16189
    @throw invalid_iterator.202 if @a pos is not an iterator of *this;
16190
    example: `"iterator does not fit current value"`
16191
16192
    @return iterator pointing to the first element inserted, or @a pos if
16193
    `ilist` is empty
16194
16195
    @complexity Linear in `ilist.size()` plus linear in the distance between
16196
    @a pos and end of the container.
16197
16198
    @liveexample{The example shows how `insert()` is used.,insert__ilist}
16199
16200
    @since version 1.0.0
16201
    */
16202
    iterator insert(const_iterator pos, initializer_list_t ilist)
16203
    {
16204
        // insert only works for arrays
16205
        if (JSON_UNLIKELY(not is_array()))
16206
        {
16207
            JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
16208
        }
16209
16210
        // check if iterator pos fits to this JSON value
16211
        if (JSON_UNLIKELY(pos.m_object != this))
16212
        {
16213
            JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
16214
        }
16215
16216
        // insert to array and return iterator
16217
        iterator result(this);
16218
        result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist.begin(), ilist.end());
16219
        return result;
16220
    }
16221
16222
    /*!
16223
    @brief inserts elements
16224
16225
    Inserts elements from range `[first, last)`.
16226
16227
    @param[in] first begin of the range of elements to insert
16228
    @param[in] last end of the range of elements to insert
16229
16230
    @throw type_error.309 if called on JSON values other than objects; example:
16231
    `"cannot use insert() with string"`
16232
    @throw invalid_iterator.202 if iterator @a first or @a last does does not
16233
    point to an object; example: `"iterators first and last must point to
16234
    objects"`
16235
    @throw invalid_iterator.210 if @a first and @a last do not belong to the
16236
    same JSON value; example: `"iterators do not fit"`
16237
16238
    @complexity Logarithmic: `O(N*log(size() + N))`, where `N` is the number
16239
    of elements to insert.
16240
16241
    @liveexample{The example shows how `insert()` is used.,insert__range_object}
16242
16243
    @since version 3.0.0
16244
    */
16245
    void insert(const_iterator first, const_iterator last)
16246
    {
16247
        // insert only works for objects
16248
        if (JSON_UNLIKELY(not is_object()))
16249
        {
16250
            JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
16251
        }
16252
16253
        // check if range iterators belong to the same JSON object
16254
        if (JSON_UNLIKELY(first.m_object != last.m_object))
16255
        {
16256
            JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
16257
        }
16258
16259
        // passed iterators must belong to objects
16260
        if (JSON_UNLIKELY(not first.m_object->is_object()))
16261
        {
16262
            JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects"));
16263
        }
16264
16265
        m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
16266
    }
16267
16268
    /*!
16269
    @brief updates a JSON object from another object, overwriting existing keys
16270
16271
    Inserts all values from JSON object @a j and overwrites existing keys.
16272
16273
    @param[in] j  JSON object to read values from
16274
16275
    @throw type_error.312 if called on JSON values other than objects; example:
16276
    `"cannot use update() with string"`
16277
16278
    @complexity O(N*log(size() + N)), where N is the number of elements to
16279
                insert.
16280
16281
    @liveexample{The example shows how `update()` is used.,update}
16282
16283
    @sa https://docs.python.org/3.6/library/stdtypes.html#dict.update
16284
16285
    @since version 3.0.0
16286
    */
16287
    void update(const_reference j)
16288
    {
16289
        // implicitly convert null value to an empty object
16290
        if (is_null())
16291
        {
16292
            m_type = value_t::object;
16293
            m_value.object = create<object_t>();
16294
            assert_invariant();
16295
        }
16296
16297
        if (JSON_UNLIKELY(not is_object()))
16298
        {
16299
            JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name())));
16300
        }
16301
        if (JSON_UNLIKELY(not j.is_object()))
16302
        {
16303
            JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(j.type_name())));
16304
        }
16305
16306
        for (auto it = j.cbegin(); it != j.cend(); ++it)
16307
        {
16308
            m_value.object->operator[](it.key()) = it.value();
16309
        }
16310
    }
16311
16312
    /*!
16313
    @brief updates a JSON object from another object, overwriting existing keys
16314
16315
    Inserts all values from from range `[first, last)` and overwrites existing
16316
    keys.
16317
16318
    @param[in] first begin of the range of elements to insert
16319
    @param[in] last end of the range of elements to insert
16320
16321
    @throw type_error.312 if called on JSON values other than objects; example:
16322
    `"cannot use update() with string"`
16323
    @throw invalid_iterator.202 if iterator @a first or @a last does does not
16324
    point to an object; example: `"iterators first and last must point to
16325
    objects"`
16326
    @throw invalid_iterator.210 if @a first and @a last do not belong to the
16327
    same JSON value; example: `"iterators do not fit"`
16328
16329
    @complexity O(N*log(size() + N)), where N is the number of elements to
16330
                insert.
16331
16332
    @liveexample{The example shows how `update()` is used__range.,update}
16333
16334
    @sa https://docs.python.org/3.6/library/stdtypes.html#dict.update
16335
16336
    @since version 3.0.0
16337
    */
16338
    void update(const_iterator first, const_iterator last)
16339
    {
16340
        // implicitly convert null value to an empty object
16341
        if (is_null())
16342
        {
16343
            m_type = value_t::object;
16344
            m_value.object = create<object_t>();
16345
            assert_invariant();
16346
        }
16347
16348
        if (JSON_UNLIKELY(not is_object()))
16349
        {
16350
            JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name())));
16351
        }
16352
16353
        // check if range iterators belong to the same JSON object
16354
        if (JSON_UNLIKELY(first.m_object != last.m_object))
16355
        {
16356
            JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
16357
        }
16358
16359
        // passed iterators must belong to objects
16360
        if (JSON_UNLIKELY(not first.m_object->is_object()
16361
                          or not last.m_object->is_object()))
16362
        {
16363
            JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects"));
16364
        }
16365
16366
        for (auto it = first; it != last; ++it)
16367
        {
16368
            m_value.object->operator[](it.key()) = it.value();
16369
        }
16370
    }
16371
16372
    /*!
16373
    @brief exchanges the values
16374
16375
    Exchanges the contents of the JSON value with those of @a other. Does not
16376
    invoke any move, copy, or swap operations on individual elements. All
16377
    iterators and references remain valid. The past-the-end iterator is
16378
    invalidated.
16379
16380
    @param[in,out] other JSON value to exchange the contents with
16381
16382
    @complexity Constant.
16383
16384
    @liveexample{The example below shows how JSON values can be swapped with
16385
    `swap()`.,swap__reference}
16386
16387
    @since version 1.0.0
16388
    */
16389
    void swap(reference other) noexcept (
16390
        std::is_nothrow_move_constructible<value_t>::value and
16391
        std::is_nothrow_move_assignable<value_t>::value and
16392
        std::is_nothrow_move_constructible<json_value>::value and
16393
        std::is_nothrow_move_assignable<json_value>::value
16394
    )
16395
0
    {
16396
0
        std::swap(m_type, other.m_type);
16397
0
        std::swap(m_value, other.m_value);
16398
0
        assert_invariant();
16399
0
    }
16400
16401
    /*!
16402
    @brief exchanges the values
16403
16404
    Exchanges the contents of a JSON array with those of @a other. Does not
16405
    invoke any move, copy, or swap operations on individual elements. All
16406
    iterators and references remain valid. The past-the-end iterator is
16407
    invalidated.
16408
16409
    @param[in,out] other array to exchange the contents with
16410
16411
    @throw type_error.310 when JSON value is not an array; example: `"cannot
16412
    use swap() with string"`
16413
16414
    @complexity Constant.
16415
16416
    @liveexample{The example below shows how arrays can be swapped with
16417
    `swap()`.,swap__array_t}
16418
16419
    @since version 1.0.0
16420
    */
16421
    void swap(array_t& other)
16422
    {
16423
        // swap only works for arrays
16424
        if (JSON_LIKELY(is_array()))
16425
        {
16426
            std::swap(*(m_value.array), other);
16427
        }
16428
        else
16429
        {
16430
            JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
16431
        }
16432
    }
16433
16434
    /*!
16435
    @brief exchanges the values
16436
16437
    Exchanges the contents of a JSON object with those of @a other. Does not
16438
    invoke any move, copy, or swap operations on individual elements. All
16439
    iterators and references remain valid. The past-the-end iterator is
16440
    invalidated.
16441
16442
    @param[in,out] other object to exchange the contents with
16443
16444
    @throw type_error.310 when JSON value is not an object; example:
16445
    `"cannot use swap() with string"`
16446
16447
    @complexity Constant.
16448
16449
    @liveexample{The example below shows how objects can be swapped with
16450
    `swap()`.,swap__object_t}
16451
16452
    @since version 1.0.0
16453
    */
16454
    void swap(object_t& other)
16455
    {
16456
        // swap only works for objects
16457
        if (JSON_LIKELY(is_object()))
16458
        {
16459
            std::swap(*(m_value.object), other);
16460
        }
16461
        else
16462
        {
16463
            JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
16464
        }
16465
    }
16466
16467
    /*!
16468
    @brief exchanges the values
16469
16470
    Exchanges the contents of a JSON string with those of @a other. Does not
16471
    invoke any move, copy, or swap operations on individual elements. All
16472
    iterators and references remain valid. The past-the-end iterator is
16473
    invalidated.
16474
16475
    @param[in,out] other string to exchange the contents with
16476
16477
    @throw type_error.310 when JSON value is not a string; example: `"cannot
16478
    use swap() with boolean"`
16479
16480
    @complexity Constant.
16481
16482
    @liveexample{The example below shows how strings can be swapped with
16483
    `swap()`.,swap__string_t}
16484
16485
    @since version 1.0.0
16486
    */
16487
    void swap(string_t& other)
16488
    {
16489
        // swap only works for strings
16490
        if (JSON_LIKELY(is_string()))
16491
        {
16492
            std::swap(*(m_value.string), other);
16493
        }
16494
        else
16495
        {
16496
            JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
16497
        }
16498
    }
16499
16500
    /// @}
16501
16502
  public:
16503
    //////////////////////////////////////////
16504
    // lexicographical comparison operators //
16505
    //////////////////////////////////////////
16506
16507
    /// @name lexicographical comparison operators
16508
    /// @{
16509
16510
    /*!
16511
    @brief comparison: equal
16512
16513
    Compares two JSON values for equality according to the following rules:
16514
    - Two JSON values are equal if (1) they are from the same type and (2)
16515
      their stored values are the same according to their respective
16516
      `operator==`.
16517
    - Integer and floating-point numbers are automatically converted before
16518
      comparison. Note than two NaN values are always treated as unequal.
16519
    - Two JSON null values are equal.
16520
16521
    @note Floating-point inside JSON values numbers are compared with
16522
    `json::number_float_t::operator==` which is `double::operator==` by
16523
    default. To compare floating-point while respecting an epsilon, an alternative
16524
    [comparison function](https://github.com/mariokonrad/marnav/blob/master/src/marnav/math/floatingpoint.hpp#L34-#L39)
16525
    could be used, for instance
16526
    @code {.cpp}
16527
    template<typename T, typename = typename std::enable_if<std::is_floating_point<T>::value, T>::type>
16528
    inline bool is_same(T a, T b, T epsilon = std::numeric_limits<T>::epsilon()) noexcept
16529
    {
16530
        return std::abs(a - b) <= epsilon;
16531
    }
16532
    @endcode
16533
16534
    @note NaN values never compare equal to themselves or to other NaN values.
16535
16536
    @param[in] lhs  first JSON value to consider
16537
    @param[in] rhs  second JSON value to consider
16538
    @return whether the values @a lhs and @a rhs are equal
16539
16540
    @exceptionsafety No-throw guarantee: this function never throws exceptions.
16541
16542
    @complexity Linear.
16543
16544
    @liveexample{The example demonstrates comparing several JSON
16545
    types.,operator__equal}
16546
16547
    @since version 1.0.0
16548
    */
16549
    friend bool operator==(const_reference lhs, const_reference rhs) noexcept
16550
10
    {
16551
10
        const auto lhs_type = lhs.type();
16552
10
        const auto rhs_type = rhs.type();
16553
10
16554
10
        if (lhs_type == rhs_type)
16555
10
        {
16556
10
            switch (lhs_type)
16557
0
            {
16558
0
                case value_t::array:
16559
0
                    return (*lhs.m_value.array == *rhs.m_value.array);
16560
0
16561
0
                case value_t::object:
16562
0
                    return (*lhs.m_value.object == *rhs.m_value.object);
16563
0
16564
0
                case value_t::null:
16565
0
                    return true;
16566
0
16567
10
                case value_t::string:
16568
10
                    return (*lhs.m_value.string == *rhs.m_value.string);
16569
0
16570
0
                case value_t::boolean:
16571
0
                    return (lhs.m_value.boolean == rhs.m_value.boolean);
16572
0
16573
0
                case value_t::number_integer:
16574
0
                    return (lhs.m_value.number_integer == rhs.m_value.number_integer);
16575
0
16576
0
                case value_t::number_unsigned:
16577
0
                    return (lhs.m_value.number_unsigned == rhs.m_value.number_unsigned);
16578
0
16579
0
                case value_t::number_float:
16580
0
                    return (lhs.m_value.number_float == rhs.m_value.number_float);
16581
0
16582
0
                default:
16583
0
                    return false;
16584
0
            }
16585
10
        }
16586
10
        else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
16587
0
        {
16588
0
            return (static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float);
16589
0
        }
16590
0
        else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
16591
0
        {
16592
0
            return (lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer));
16593
0
        }
16594
0
        else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
16595
0
        {
16596
0
            return (static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float);
16597
0
        }
16598
0
        else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
16599
0
        {
16600
0
            return (lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned));
16601
0
        }
16602
0
        else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
16603
0
        {
16604
0
            return (static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer);
16605
0
        }
16606
0
        else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
16607
0
        {
16608
0
            return (lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned));
16609
0
        }
16610
10
16611
10
        return false;
16612
10
    }
16613
16614
    /*!
16615
    @brief comparison: equal
16616
    @copydoc operator==(const_reference, const_reference)
16617
    */
16618
    template<typename ScalarType, typename std::enable_if<
16619
                 std::is_scalar<ScalarType>::value, int>::type = 0>
16620
    friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept
16621
10
    {
16622
10
        return (lhs == basic_json(rhs));
16623
10
    }
16624
16625
    /*!
16626
    @brief comparison: equal
16627
    @copydoc operator==(const_reference, const_reference)
16628
    */
16629
    template<typename ScalarType, typename std::enable_if<
16630
                 std::is_scalar<ScalarType>::value, int>::type = 0>
16631
    friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept
16632
    {
16633
        return (basic_json(lhs) == rhs);
16634
    }
16635
16636
    /*!
16637
    @brief comparison: not equal
16638
16639
    Compares two JSON values for inequality by calculating `not (lhs == rhs)`.
16640
16641
    @param[in] lhs  first JSON value to consider
16642
    @param[in] rhs  second JSON value to consider
16643
    @return whether the values @a lhs and @a rhs are not equal
16644
16645
    @complexity Linear.
16646
16647
    @exceptionsafety No-throw guarantee: this function never throws exceptions.
16648
16649
    @liveexample{The example demonstrates comparing several JSON
16650
    types.,operator__notequal}
16651
16652
    @since version 1.0.0
16653
    */
16654
    friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
16655
    {
16656
        return not (lhs == rhs);
16657
    }
16658
16659
    /*!
16660
    @brief comparison: not equal
16661
    @copydoc operator!=(const_reference, const_reference)
16662
    */
16663
    template<typename ScalarType, typename std::enable_if<
16664
                 std::is_scalar<ScalarType>::value, int>::type = 0>
16665
    friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept
16666
    {
16667
        return (lhs != basic_json(rhs));
16668
    }
16669
16670
    /*!
16671
    @brief comparison: not equal
16672
    @copydoc operator!=(const_reference, const_reference)
16673
    */
16674
    template<typename ScalarType, typename std::enable_if<
16675
                 std::is_scalar<ScalarType>::value, int>::type = 0>
16676
    friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept
16677
    {
16678
        return (basic_json(lhs) != rhs);
16679
    }
16680
16681
    /*!
16682
    @brief comparison: less than
16683
16684
    Compares whether one JSON value @a lhs is less than another JSON value @a
16685
    rhs according to the following rules:
16686
    - If @a lhs and @a rhs have the same type, the values are compared using
16687
      the default `<` operator.
16688
    - Integer and floating-point numbers are automatically converted before
16689
      comparison
16690
    - In case @a lhs and @a rhs have different types, the values are ignored
16691
      and the order of the types is considered, see
16692
      @ref operator<(const value_t, const value_t).
16693
16694
    @param[in] lhs  first JSON value to consider
16695
    @param[in] rhs  second JSON value to consider
16696
    @return whether @a lhs is less than @a rhs
16697
16698
    @complexity Linear.
16699
16700
    @exceptionsafety No-throw guarantee: this function never throws exceptions.
16701
16702
    @liveexample{The example demonstrates comparing several JSON
16703
    types.,operator__less}
16704
16705
    @since version 1.0.0
16706
    */
16707
    friend bool operator<(const_reference lhs, const_reference rhs) noexcept
16708
    {
16709
        const auto lhs_type = lhs.type();
16710
        const auto rhs_type = rhs.type();
16711
16712
        if (lhs_type == rhs_type)
16713
        {
16714
            switch (lhs_type)
16715
            {
16716
                case value_t::array:
16717
                    return (*lhs.m_value.array) < (*rhs.m_value.array);
16718
16719
                case value_t::object:
16720
                    return *lhs.m_value.object < *rhs.m_value.object;
16721
16722
                case value_t::null:
16723
                    return false;
16724
16725
                case value_t::string:
16726
                    return *lhs.m_value.string < *rhs.m_value.string;
16727
16728
                case value_t::boolean:
16729
                    return lhs.m_value.boolean < rhs.m_value.boolean;
16730
16731
                case value_t::number_integer:
16732
                    return lhs.m_value.number_integer < rhs.m_value.number_integer;
16733
16734
                case value_t::number_unsigned:
16735
                    return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
16736
16737
                case value_t::number_float:
16738
                    return lhs.m_value.number_float < rhs.m_value.number_float;
16739
16740
                default:
16741
                    return false;
16742
            }
16743
        }
16744
        else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
16745
        {
16746
            return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
16747
        }
16748
        else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
16749
        {
16750
            return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
16751
        }
16752
        else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
16753
        {
16754
            return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
16755
        }
16756
        else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
16757
        {
16758
            return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
16759
        }
16760
        else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
16761
        {
16762
            return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
16763
        }
16764
        else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
16765
        {
16766
            return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
16767
        }
16768
16769
        // We only reach this line if we cannot compare values. In that case,
16770
        // we compare types. Note we have to call the operator explicitly,
16771
        // because MSVC has problems otherwise.
16772
        return operator<(lhs_type, rhs_type);
16773
    }
16774
16775
    /*!
16776
    @brief comparison: less than
16777
    @copydoc operator<(const_reference, const_reference)
16778
    */
16779
    template<typename ScalarType, typename std::enable_if<
16780
                 std::is_scalar<ScalarType>::value, int>::type = 0>
16781
    friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept
16782
    {
16783
        return (lhs < basic_json(rhs));
16784
    }
16785
16786
    /*!
16787
    @brief comparison: less than
16788
    @copydoc operator<(const_reference, const_reference)
16789
    */
16790
    template<typename ScalarType, typename std::enable_if<
16791
                 std::is_scalar<ScalarType>::value, int>::type = 0>
16792
    friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept
16793
    {
16794
        return (basic_json(lhs) < rhs);
16795
    }
16796
16797
    /*!
16798
    @brief comparison: less than or equal
16799
16800
    Compares whether one JSON value @a lhs is less than or equal to another
16801
    JSON value by calculating `not (rhs < lhs)`.
16802
16803
    @param[in] lhs  first JSON value to consider
16804
    @param[in] rhs  second JSON value to consider
16805
    @return whether @a lhs is less than or equal to @a rhs
16806
16807
    @complexity Linear.
16808
16809
    @exceptionsafety No-throw guarantee: this function never throws exceptions.
16810
16811
    @liveexample{The example demonstrates comparing several JSON
16812
    types.,operator__greater}
16813
16814
    @since version 1.0.0
16815
    */
16816
    friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
16817
    {
16818
        return not (rhs < lhs);
16819
    }
16820
16821
    /*!
16822
    @brief comparison: less than or equal
16823
    @copydoc operator<=(const_reference, const_reference)
16824
    */
16825
    template<typename ScalarType, typename std::enable_if<
16826
                 std::is_scalar<ScalarType>::value, int>::type = 0>
16827
    friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept
16828
    {
16829
        return (lhs <= basic_json(rhs));
16830
    }
16831
16832
    /*!
16833
    @brief comparison: less than or equal
16834
    @copydoc operator<=(const_reference, const_reference)
16835
    */
16836
    template<typename ScalarType, typename std::enable_if<
16837
                 std::is_scalar<ScalarType>::value, int>::type = 0>
16838
    friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept
16839
    {
16840
        return (basic_json(lhs) <= rhs);
16841
    }
16842
16843
    /*!
16844
    @brief comparison: greater than
16845
16846
    Compares whether one JSON value @a lhs is greater than another
16847
    JSON value by calculating `not (lhs <= rhs)`.
16848
16849
    @param[in] lhs  first JSON value to consider
16850
    @param[in] rhs  second JSON value to consider
16851
    @return whether @a lhs is greater than to @a rhs
16852
16853
    @complexity Linear.
16854
16855
    @exceptionsafety No-throw guarantee: this function never throws exceptions.
16856
16857
    @liveexample{The example demonstrates comparing several JSON
16858
    types.,operator__lessequal}
16859
16860
    @since version 1.0.0
16861
    */
16862
    friend bool operator>(const_reference lhs, const_reference rhs) noexcept
16863
    {
16864
        return not (lhs <= rhs);
16865
    }
16866
16867
    /*!
16868
    @brief comparison: greater than
16869
    @copydoc operator>(const_reference, const_reference)
16870
    */
16871
    template<typename ScalarType, typename std::enable_if<
16872
                 std::is_scalar<ScalarType>::value, int>::type = 0>
16873
    friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept
16874
    {
16875
        return (lhs > basic_json(rhs));
16876
    }
16877
16878
    /*!
16879
    @brief comparison: greater than
16880
    @copydoc operator>(const_reference, const_reference)
16881
    */
16882
    template<typename ScalarType, typename std::enable_if<
16883
                 std::is_scalar<ScalarType>::value, int>::type = 0>
16884
    friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept
16885
    {
16886
        return (basic_json(lhs) > rhs);
16887
    }
16888
16889
    /*!
16890
    @brief comparison: greater than or equal
16891
16892
    Compares whether one JSON value @a lhs is greater than or equal to another
16893
    JSON value by calculating `not (lhs < rhs)`.
16894
16895
    @param[in] lhs  first JSON value to consider
16896
    @param[in] rhs  second JSON value to consider
16897
    @return whether @a lhs is greater than or equal to @a rhs
16898
16899
    @complexity Linear.
16900
16901
    @exceptionsafety No-throw guarantee: this function never throws exceptions.
16902
16903
    @liveexample{The example demonstrates comparing several JSON
16904
    types.,operator__greaterequal}
16905
16906
    @since version 1.0.0
16907
    */
16908
    friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
16909
    {
16910
        return not (lhs < rhs);
16911
    }
16912
16913
    /*!
16914
    @brief comparison: greater than or equal
16915
    @copydoc operator>=(const_reference, const_reference)
16916
    */
16917
    template<typename ScalarType, typename std::enable_if<
16918
                 std::is_scalar<ScalarType>::value, int>::type = 0>
16919
    friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept
16920
    {
16921
        return (lhs >= basic_json(rhs));
16922
    }
16923
16924
    /*!
16925
    @brief comparison: greater than or equal
16926
    @copydoc operator>=(const_reference, const_reference)
16927
    */
16928
    template<typename ScalarType, typename std::enable_if<
16929
                 std::is_scalar<ScalarType>::value, int>::type = 0>
16930
    friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept
16931
    {
16932
        return (basic_json(lhs) >= rhs);
16933
    }
16934
16935
    /// @}
16936
16937
    ///////////////////
16938
    // serialization //
16939
    ///////////////////
16940
16941
    /// @name serialization
16942
    /// @{
16943
16944
    /*!
16945
    @brief serialize to stream
16946
16947
    Serialize the given JSON value @a j to the output stream @a o. The JSON
16948
    value will be serialized using the @ref dump member function.
16949
16950
    - The indentation of the output can be controlled with the member variable
16951
      `width` of the output stream @a o. For instance, using the manipulator
16952
      `std::setw(4)` on @a o sets the indentation level to `4` and the
16953
      serialization result is the same as calling `dump(4)`.
16954
16955
    - The indentation character can be controlled with the member variable
16956
      `fill` of the output stream @a o. For instance, the manipulator
16957
      `std::setfill('\\t')` sets indentation to use a tab character rather than
16958
      the default space character.
16959
16960
    @param[in,out] o  stream to serialize to
16961
    @param[in] j  JSON value to serialize
16962
16963
    @return the stream @a o
16964
16965
    @throw type_error.316 if a string stored inside the JSON value is not
16966
                          UTF-8 encoded
16967
16968
    @complexity Linear.
16969
16970
    @liveexample{The example below shows the serialization with different
16971
    parameters to `width` to adjust the indentation level.,operator_serialize}
16972
16973
    @since version 1.0.0; indentation character added in version 3.0.0
16974
    */
16975
    friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
16976
105
    {
16977
105
        // read width member and use it as indentation parameter if nonzero
16978
105
        const bool pretty_print = (o.width() > 0);
16979
105
        const auto indentation = (pretty_print ? o.width() : 0);
16980
105
16981
105
        // reset width to 0 for subsequent calls to this stream
16982
105
        o.width(0);
16983
105
16984
105
        // do the actual serialization
16985
105
        serializer s(detail::output_adapter<char>(o), o.fill());
16986
105
        s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
16987
105
        return o;
16988
105
    }
16989
16990
    /*!
16991
    @brief serialize to stream
16992
    @deprecated This stream operator is deprecated and will be removed in
16993
                future 4.0.0 of the library. Please use
16994
                @ref operator<<(std::ostream&, const basic_json&)
16995
                instead; that is, replace calls like `j >> o;` with `o << j;`.
16996
    @since version 1.0.0; deprecated since version 3.0.0
16997
    */
16998
    JSON_DEPRECATED
16999
    friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
17000
    {
17001
        return o << j;
17002
    }
17003
17004
    /// @}
17005
17006
17007
    /////////////////////
17008
    // deserialization //
17009
    /////////////////////
17010
17011
    /// @name deserialization
17012
    /// @{
17013
17014
    /*!
17015
    @brief deserialize from a compatible input
17016
17017
    This function reads from a compatible input. Examples are:
17018
    - an array of 1-byte values
17019
    - strings with character/literal type with size of 1 byte
17020
    - input streams
17021
    - container with contiguous storage of 1-byte values. Compatible container
17022
      types include `std::vector`, `std::string`, `std::array`,
17023
      `std::valarray`, and `std::initializer_list`. Furthermore, C-style
17024
      arrays can be used with `std::begin()`/`std::end()`. User-defined
17025
      containers can be used as long as they implement random-access iterators
17026
      and a contiguous storage.
17027
17028
    @pre Each element of the container has a size of 1 byte. Violating this
17029
    precondition yields undefined behavior. **This precondition is enforced
17030
    with a static assertion.**
17031
17032
    @pre The container storage is contiguous. Violating this precondition
17033
    yields undefined behavior. **This precondition is enforced with an
17034
    assertion.**
17035
    @pre Each element of the container has a size of 1 byte. Violating this
17036
    precondition yields undefined behavior. **This precondition is enforced
17037
    with a static assertion.**
17038
17039
    @warning There is no way to enforce all preconditions at compile-time. If
17040
             the function is called with a noncompliant container and with
17041
             assertions switched off, the behavior is undefined and will most
17042
             likely yield segmentation violation.
17043
17044
    @param[in] i  input to read from
17045
    @param[in] cb  a parser callback function of type @ref parser_callback_t
17046
    which is used to control the deserialization by filtering unwanted values
17047
    (optional)
17048
17049
    @return result of the deserialization
17050
17051
    @throw parse_error.101 if a parse error occurs; example: `""unexpected end
17052
    of input; expected string literal""`
17053
    @throw parse_error.102 if to_unicode fails or surrogate error
17054
    @throw parse_error.103 if to_unicode fails
17055
17056
    @complexity Linear in the length of the input. The parser is a predictive
17057
    LL(1) parser. The complexity can be higher if the parser callback function
17058
    @a cb has a super-linear complexity.
17059
17060
    @note A UTF-8 byte order mark is silently ignored.
17061
17062
    @liveexample{The example below demonstrates the `parse()` function reading
17063
    from an array.,parse__array__parser_callback_t}
17064
17065
    @liveexample{The example below demonstrates the `parse()` function with
17066
    and without callback function.,parse__string__parser_callback_t}
17067
17068
    @liveexample{The example below demonstrates the `parse()` function with
17069
    and without callback function.,parse__istream__parser_callback_t}
17070
17071
    @liveexample{The example below demonstrates the `parse()` function reading
17072
    from a contiguous container.,parse__contiguouscontainer__parser_callback_t}
17073
17074
    @since version 2.0.3 (contiguous containers)
17075
    */
17076
    static basic_json parse(detail::input_adapter&& i,
17077
                            const parser_callback_t cb = nullptr,
17078
                            const bool allow_exceptions = true)
17079
637
    {
17080
637
        basic_json result;
17081
637
        parser(i, cb, allow_exceptions).parse(true, result);
17082
637
        return result;
17083
637
    }
17084
17085
    static bool accept(detail::input_adapter&& i)
17086
    {
17087
        return parser(i).accept(true);
17088
    }
17089
17090
    /*!
17091
    @brief generate SAX events
17092
17093
    The SAX event lister must follow the interface of @ref json_sax.
17094
17095
    This function reads from a compatible input. Examples are:
17096
    - an array of 1-byte values
17097
    - strings with character/literal type with size of 1 byte
17098
    - input streams
17099
    - container with contiguous storage of 1-byte values. Compatible container
17100
      types include `std::vector`, `std::string`, `std::array`,
17101
      `std::valarray`, and `std::initializer_list`. Furthermore, C-style
17102
      arrays can be used with `std::begin()`/`std::end()`. User-defined
17103
      containers can be used as long as they implement random-access iterators
17104
      and a contiguous storage.
17105
17106
    @pre Each element of the container has a size of 1 byte. Violating this
17107
    precondition yields undefined behavior. **This precondition is enforced
17108
    with a static assertion.**
17109
17110
    @pre The container storage is contiguous. Violating this precondition
17111
    yields undefined behavior. **This precondition is enforced with an
17112
    assertion.**
17113
    @pre Each element of the container has a size of 1 byte. Violating this
17114
    precondition yields undefined behavior. **This precondition is enforced
17115
    with a static assertion.**
17116
17117
    @warning There is no way to enforce all preconditions at compile-time. If
17118
             the function is called with a noncompliant container and with
17119
             assertions switched off, the behavior is undefined and will most
17120
             likely yield segmentation violation.
17121
17122
    @param[in] i  input to read from
17123
    @param[in,out] sax  SAX event listener
17124
    @param[in] format  the format to parse (JSON, CBOR, MessagePack, or UBJSON)
17125
    @param[in] strict  whether the input has to be consumed completely
17126
17127
    @return return value of the last processed SAX event
17128
17129
    @throw parse_error.101 if a parse error occurs; example: `""unexpected end
17130
    of input; expected string literal""`
17131
    @throw parse_error.102 if to_unicode fails or surrogate error
17132
    @throw parse_error.103 if to_unicode fails
17133
17134
    @complexity Linear in the length of the input. The parser is a predictive
17135
    LL(1) parser. The complexity can be higher if the SAX consumer @a sax has
17136
    a super-linear complexity.
17137
17138
    @note A UTF-8 byte order mark is silently ignored.
17139
17140
    @liveexample{The example below demonstrates the `sax_parse()` function
17141
    reading from string and processing the events with a user-defined SAX
17142
    event consumer.,sax_parse}
17143
17144
    @since version 3.2.0
17145
    */
17146
    template <typename SAX>
17147
    static bool sax_parse(detail::input_adapter&& i, SAX* sax,
17148
                          input_format_t format = input_format_t::json,
17149
                          const bool strict = true)
17150
    {
17151
        assert(sax);
17152
        switch (format)
17153
        {
17154
            case input_format_t::json:
17155
                return parser(std::move(i)).sax_parse(sax, strict);
17156
            default:
17157
                return detail::binary_reader<basic_json, SAX>(std::move(i)).sax_parse(format, sax, strict);
17158
        }
17159
    }
17160
17161
    /*!
17162
    @brief deserialize from an iterator range with contiguous storage
17163
17164
    This function reads from an iterator range of a container with contiguous
17165
    storage of 1-byte values. Compatible container types include
17166
    `std::vector`, `std::string`, `std::array`, `std::valarray`, and
17167
    `std::initializer_list`. Furthermore, C-style arrays can be used with
17168
    `std::begin()`/`std::end()`. User-defined containers can be used as long
17169
    as they implement random-access iterators and a contiguous storage.
17170
17171
    @pre The iterator range is contiguous. Violating this precondition yields
17172
    undefined behavior. **This precondition is enforced with an assertion.**
17173
    @pre Each element in the range has a size of 1 byte. Violating this
17174
    precondition yields undefined behavior. **This precondition is enforced
17175
    with a static assertion.**
17176
17177
    @warning There is no way to enforce all preconditions at compile-time. If
17178
             the function is called with noncompliant iterators and with
17179
             assertions switched off, the behavior is undefined and will most
17180
             likely yield segmentation violation.
17181
17182
    @tparam IteratorType iterator of container with contiguous storage
17183
    @param[in] first  begin of the range to parse (included)
17184
    @param[in] last  end of the range to parse (excluded)
17185
    @param[in] cb  a parser callback function of type @ref parser_callback_t
17186
    which is used to control the deserialization by filtering unwanted values
17187
    (optional)
17188
    @param[in] allow_exceptions  whether to throw exceptions in case of a
17189
    parse error (optional, true by default)
17190
17191
    @return result of the deserialization
17192
17193
    @throw parse_error.101 in case of an unexpected token
17194
    @throw parse_error.102 if to_unicode fails or surrogate error
17195
    @throw parse_error.103 if to_unicode fails
17196
17197
    @complexity Linear in the length of the input. The parser is a predictive
17198
    LL(1) parser. The complexity can be higher if the parser callback function
17199
    @a cb has a super-linear complexity.
17200
17201
    @note A UTF-8 byte order mark is silently ignored.
17202
17203
    @liveexample{The example below demonstrates the `parse()` function reading
17204
    from an iterator range.,parse__iteratortype__parser_callback_t}
17205
17206
    @since version 2.0.3
17207
    */
17208
    template<class IteratorType, typename std::enable_if<
17209
                 std::is_base_of<
17210
                     std::random_access_iterator_tag,
17211
                     typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
17212
    static basic_json parse(IteratorType first, IteratorType last,
17213
                            const parser_callback_t cb = nullptr,
17214
                            const bool allow_exceptions = true)
17215
0
    {
17216
0
        basic_json result;
17217
0
        parser(detail::input_adapter(first, last), cb, allow_exceptions).parse(true, result);
17218
0
        return result;
17219
0
    }
17220
17221
    template<class IteratorType, typename std::enable_if<
17222
                 std::is_base_of<
17223
                     std::random_access_iterator_tag,
17224
                     typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
17225
    static bool accept(IteratorType first, IteratorType last)
17226
    {
17227
        return parser(detail::input_adapter(first, last)).accept(true);
17228
    }
17229
17230
    template<class IteratorType, class SAX, typename std::enable_if<
17231
                 std::is_base_of<
17232
                     std::random_access_iterator_tag,
17233
                     typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
17234
    static bool sax_parse(IteratorType first, IteratorType last, SAX* sax)
17235
    {
17236
        return parser(detail::input_adapter(first, last)).sax_parse(sax);
17237
    }
17238
17239
    /*!
17240
    @brief deserialize from stream
17241
    @deprecated This stream operator is deprecated and will be removed in
17242
                version 4.0.0 of the library. Please use
17243
                @ref operator>>(std::istream&, basic_json&)
17244
                instead; that is, replace calls like `j << i;` with `i >> j;`.
17245
    @since version 1.0.0; deprecated since version 3.0.0
17246
    */
17247
    JSON_DEPRECATED
17248
    friend std::istream& operator<<(basic_json& j, std::istream& i)
17249
    {
17250
        return operator>>(i, j);
17251
    }
17252
17253
    /*!
17254
    @brief deserialize from stream
17255
17256
    Deserializes an input stream to a JSON value.
17257
17258
    @param[in,out] i  input stream to read a serialized JSON value from
17259
    @param[in,out] j  JSON value to write the deserialized input to
17260
17261
    @throw parse_error.101 in case of an unexpected token
17262
    @throw parse_error.102 if to_unicode fails or surrogate error
17263
    @throw parse_error.103 if to_unicode fails
17264
17265
    @complexity Linear in the length of the input. The parser is a predictive
17266
    LL(1) parser.
17267
17268
    @note A UTF-8 byte order mark is silently ignored.
17269
17270
    @liveexample{The example below shows how a JSON value is constructed by
17271
    reading a serialization from a stream.,operator_deserialize}
17272
17273
    @sa parse(std::istream&, const parser_callback_t) for a variant with a
17274
    parser callback function to filter values while parsing
17275
17276
    @since version 1.0.0
17277
    */
17278
    friend std::istream& operator>>(std::istream& i, basic_json& j)
17279
198
    {
17280
198
        parser(detail::input_adapter(i)).parse(false, j);
17281
198
        return i;
17282
198
    }
17283
17284
    /// @}
17285
17286
    ///////////////////////////
17287
    // convenience functions //
17288
    ///////////////////////////
17289
17290
    /*!
17291
    @brief return the type as string
17292
17293
    Returns the type name as string to be used in error messages - usually to
17294
    indicate that a function was called on a wrong JSON type.
17295
17296
    @return a string representation of a the @a m_type member:
17297
            Value type  | return value
17298
            ----------- | -------------
17299
            null        | `"null"`
17300
            boolean     | `"boolean"`
17301
            string      | `"string"`
17302
            number      | `"number"` (for all number types)
17303
            object      | `"object"`
17304
            array       | `"array"`
17305
            discarded   | `"discarded"`
17306
17307
    @exceptionsafety No-throw guarantee: this function never throws exceptions.
17308
17309
    @complexity Constant.
17310
17311
    @liveexample{The following code exemplifies `type_name()` for all JSON
17312
    types.,type_name}
17313
17314
    @sa @ref type() -- return the type of the JSON value
17315
    @sa @ref operator value_t() -- return the type of the JSON value (implicit)
17316
17317
    @since version 1.0.0, public since 2.1.0, `const char*` and `noexcept`
17318
    since 3.0.0
17319
    */
17320
    const char* type_name() const noexcept
17321
0
    {
17322
0
        {
17323
0
            switch (m_type)
17324
0
            {
17325
0
                case value_t::null:
17326
0
                    return "null";
17327
0
                case value_t::object:
17328
0
                    return "object";
17329
0
                case value_t::array:
17330
0
                    return "array";
17331
0
                case value_t::string:
17332
0
                    return "string";
17333
0
                case value_t::boolean:
17334
0
                    return "boolean";
17335
0
                case value_t::discarded:
17336
0
                    return "discarded";
17337
0
                default:
17338
0
                    return "number";
17339
0
            }
17340
0
        }
17341
0
    }
17342
17343
17344
  private:
17345
    //////////////////////
17346
    // member variables //
17347
    //////////////////////
17348
17349
    /// the type of the current element
17350
    value_t m_type = value_t::null;
17351
17352
    /// the value of the current element
17353
    json_value m_value = {};
17354
17355
    //////////////////////////////////////////
17356
    // binary serialization/deserialization //
17357
    //////////////////////////////////////////
17358
17359
    /// @name binary serialization/deserialization support
17360
    /// @{
17361
17362
  public:
17363
    /*!
17364
    @brief create a CBOR serialization of a given JSON value
17365
17366
    Serializes a given JSON value @a j to a byte vector using the CBOR (Concise
17367
    Binary Object Representation) serialization format. CBOR is a binary
17368
    serialization format which aims to be more compact than JSON itself, yet
17369
    more efficient to parse.
17370
17371
    The library uses the following mapping from JSON values types to
17372
    CBOR types according to the CBOR specification (RFC 7049):
17373
17374
    JSON value type | value/range                                | CBOR type                          | first byte
17375
    --------------- | ------------------------------------------ | ---------------------------------- | ---------------
17376
    null            | `null`                                     | Null                               | 0xF6
17377
    boolean         | `true`                                     | True                               | 0xF5
17378
    boolean         | `false`                                    | False                              | 0xF4
17379
    number_integer  | -9223372036854775808..-2147483649          | Negative integer (8 bytes follow)  | 0x3B
17380
    number_integer  | -2147483648..-32769                        | Negative integer (4 bytes follow)  | 0x3A
17381
    number_integer  | -32768..-129                               | Negative integer (2 bytes follow)  | 0x39
17382
    number_integer  | -128..-25                                  | Negative integer (1 byte follow)   | 0x38
17383
    number_integer  | -24..-1                                    | Negative integer                   | 0x20..0x37
17384
    number_integer  | 0..23                                      | Integer                            | 0x00..0x17
17385
    number_integer  | 24..255                                    | Unsigned integer (1 byte follow)   | 0x18
17386
    number_integer  | 256..65535                                 | Unsigned integer (2 bytes follow)  | 0x19
17387
    number_integer  | 65536..4294967295                          | Unsigned integer (4 bytes follow)  | 0x1A
17388
    number_integer  | 4294967296..18446744073709551615           | Unsigned integer (8 bytes follow)  | 0x1B
17389
    number_unsigned | 0..23                                      | Integer                            | 0x00..0x17
17390
    number_unsigned | 24..255                                    | Unsigned integer (1 byte follow)   | 0x18
17391
    number_unsigned | 256..65535                                 | Unsigned integer (2 bytes follow)  | 0x19
17392
    number_unsigned | 65536..4294967295                          | Unsigned integer (4 bytes follow)  | 0x1A
17393
    number_unsigned | 4294967296..18446744073709551615           | Unsigned integer (8 bytes follow)  | 0x1B
17394
    number_float    | *any value*                                | Double-Precision Float             | 0xFB
17395
    string          | *length*: 0..23                            | UTF-8 string                       | 0x60..0x77
17396
    string          | *length*: 23..255                          | UTF-8 string (1 byte follow)       | 0x78
17397
    string          | *length*: 256..65535                       | UTF-8 string (2 bytes follow)      | 0x79
17398
    string          | *length*: 65536..4294967295                | UTF-8 string (4 bytes follow)      | 0x7A
17399
    string          | *length*: 4294967296..18446744073709551615 | UTF-8 string (8 bytes follow)      | 0x7B
17400
    array           | *size*: 0..23                              | array                              | 0x80..0x97
17401
    array           | *size*: 23..255                            | array (1 byte follow)              | 0x98
17402
    array           | *size*: 256..65535                         | array (2 bytes follow)             | 0x99
17403
    array           | *size*: 65536..4294967295                  | array (4 bytes follow)             | 0x9A
17404
    array           | *size*: 4294967296..18446744073709551615   | array (8 bytes follow)             | 0x9B
17405
    object          | *size*: 0..23                              | map                                | 0xA0..0xB7
17406
    object          | *size*: 23..255                            | map (1 byte follow)                | 0xB8
17407
    object          | *size*: 256..65535                         | map (2 bytes follow)               | 0xB9
17408
    object          | *size*: 65536..4294967295                  | map (4 bytes follow)               | 0xBA
17409
    object          | *size*: 4294967296..18446744073709551615   | map (8 bytes follow)               | 0xBB
17410
17411
    @note The mapping is **complete** in the sense that any JSON value type
17412
          can be converted to a CBOR value.
17413
17414
    @note If NaN or Infinity are stored inside a JSON number, they are
17415
          serialized properly. This behavior differs from the @ref dump()
17416
          function which serializes NaN or Infinity to `null`.
17417
17418
    @note The following CBOR types are not used in the conversion:
17419
          - byte strings (0x40..0x5F)
17420
          - UTF-8 strings terminated by "break" (0x7F)
17421
          - arrays terminated by "break" (0x9F)
17422
          - maps terminated by "break" (0xBF)
17423
          - date/time (0xC0..0xC1)
17424
          - bignum (0xC2..0xC3)
17425
          - decimal fraction (0xC4)
17426
          - bigfloat (0xC5)
17427
          - tagged items (0xC6..0xD4, 0xD8..0xDB)
17428
          - expected conversions (0xD5..0xD7)
17429
          - simple values (0xE0..0xF3, 0xF8)
17430
          - undefined (0xF7)
17431
          - half and single-precision floats (0xF9-0xFA)
17432
          - break (0xFF)
17433
17434
    @param[in] j  JSON value to serialize
17435
    @return MessagePack serialization as byte vector
17436
17437
    @complexity Linear in the size of the JSON value @a j.
17438
17439
    @liveexample{The example shows the serialization of a JSON value to a byte
17440
    vector in CBOR format.,to_cbor}
17441
17442
    @sa http://cbor.io
17443
    @sa @ref from_cbor(detail::input_adapter, const bool strict) for the
17444
        analogous deserialization
17445
    @sa @ref to_msgpack(const basic_json&) for the related MessagePack format
17446
    @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
17447
             related UBJSON format
17448
17449
    @since version 2.0.9
17450
    */
17451
    static std::vector<uint8_t> to_cbor(const basic_json& j)
17452
    {
17453
        std::vector<uint8_t> result;
17454
        to_cbor(j, result);
17455
        return result;
17456
    }
17457
17458
    static void to_cbor(const basic_json& j, detail::output_adapter<uint8_t> o)
17459
    {
17460
        binary_writer<uint8_t>(o).write_cbor(j);
17461
    }
17462
17463
    static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
17464
    {
17465
        binary_writer<char>(o).write_cbor(j);
17466
    }
17467
17468
    /*!
17469
    @brief create a MessagePack serialization of a given JSON value
17470
17471
    Serializes a given JSON value @a j to a byte vector using the MessagePack
17472
    serialization format. MessagePack is a binary serialization format which
17473
    aims to be more compact than JSON itself, yet more efficient to parse.
17474
17475
    The library uses the following mapping from JSON values types to
17476
    MessagePack types according to the MessagePack specification:
17477
17478
    JSON value type | value/range                       | MessagePack type | first byte
17479
    --------------- | --------------------------------- | ---------------- | ----------
17480
    null            | `null`                            | nil              | 0xC0
17481
    boolean         | `true`                            | true             | 0xC3
17482
    boolean         | `false`                           | false            | 0xC2
17483
    number_integer  | -9223372036854775808..-2147483649 | int64            | 0xD3
17484
    number_integer  | -2147483648..-32769               | int32            | 0xD2
17485
    number_integer  | -32768..-129                      | int16            | 0xD1
17486
    number_integer  | -128..-33                         | int8             | 0xD0
17487
    number_integer  | -32..-1                           | negative fixint  | 0xE0..0xFF
17488
    number_integer  | 0..127                            | positive fixint  | 0x00..0x7F
17489
    number_integer  | 128..255                          | uint 8           | 0xCC
17490
    number_integer  | 256..65535                        | uint 16          | 0xCD
17491
    number_integer  | 65536..4294967295                 | uint 32          | 0xCE
17492
    number_integer  | 4294967296..18446744073709551615  | uint 64          | 0xCF
17493
    number_unsigned | 0..127                            | positive fixint  | 0x00..0x7F
17494
    number_unsigned | 128..255                          | uint 8           | 0xCC
17495
    number_unsigned | 256..65535                        | uint 16          | 0xCD
17496
    number_unsigned | 65536..4294967295                 | uint 32          | 0xCE
17497
    number_unsigned | 4294967296..18446744073709551615  | uint 64          | 0xCF
17498
    number_float    | *any value*                       | float 64         | 0xCB
17499
    string          | *length*: 0..31                   | fixstr           | 0xA0..0xBF
17500
    string          | *length*: 32..255                 | str 8            | 0xD9
17501
    string          | *length*: 256..65535              | str 16           | 0xDA
17502
    string          | *length*: 65536..4294967295       | str 32           | 0xDB
17503
    array           | *size*: 0..15                     | fixarray         | 0x90..0x9F
17504
    array           | *size*: 16..65535                 | array 16         | 0xDC
17505
    array           | *size*: 65536..4294967295         | array 32         | 0xDD
17506
    object          | *size*: 0..15                     | fix map          | 0x80..0x8F
17507
    object          | *size*: 16..65535                 | map 16           | 0xDE
17508
    object          | *size*: 65536..4294967295         | map 32           | 0xDF
17509
17510
    @note The mapping is **complete** in the sense that any JSON value type
17511
          can be converted to a MessagePack value.
17512
17513
    @note The following values can **not** be converted to a MessagePack value:
17514
          - strings with more than 4294967295 bytes
17515
          - arrays with more than 4294967295 elements
17516
          - objects with more than 4294967295 elements
17517
17518
    @note The following MessagePack types are not used in the conversion:
17519
          - bin 8 - bin 32 (0xC4..0xC6)
17520
          - ext 8 - ext 32 (0xC7..0xC9)
17521
          - float 32 (0xCA)
17522
          - fixext 1 - fixext 16 (0xD4..0xD8)
17523
17524
    @note Any MessagePack output created @ref to_msgpack can be successfully
17525
          parsed by @ref from_msgpack.
17526
17527
    @note If NaN or Infinity are stored inside a JSON number, they are
17528
          serialized properly. This behavior differs from the @ref dump()
17529
          function which serializes NaN or Infinity to `null`.
17530
17531
    @param[in] j  JSON value to serialize
17532
    @return MessagePack serialization as byte vector
17533
17534
    @complexity Linear in the size of the JSON value @a j.
17535
17536
    @liveexample{The example shows the serialization of a JSON value to a byte
17537
    vector in MessagePack format.,to_msgpack}
17538
17539
    @sa http://msgpack.org
17540
    @sa @ref from_msgpack(const std::vector<uint8_t>&, const size_t) for the
17541
        analogous deserialization
17542
    @sa @ref to_cbor(const basic_json& for the related CBOR format
17543
    @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
17544
             related UBJSON format
17545
17546
    @since version 2.0.9
17547
    */
17548
    static std::vector<uint8_t> to_msgpack(const basic_json& j)
17549
    {
17550
        std::vector<uint8_t> result;
17551
        to_msgpack(j, result);
17552
        return result;
17553
    }
17554
17555
    static void to_msgpack(const basic_json& j, detail::output_adapter<uint8_t> o)
17556
    {
17557
        binary_writer<uint8_t>(o).write_msgpack(j);
17558
    }
17559
17560
    static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
17561
    {
17562
        binary_writer<char>(o).write_msgpack(j);
17563
    }
17564
17565
    /*!
17566
    @brief create a UBJSON serialization of a given JSON value
17567
17568
    Serializes a given JSON value @a j to a byte vector using the UBJSON
17569
    (Universal Binary JSON) serialization format. UBJSON aims to be more compact
17570
    than JSON itself, yet more efficient to parse.
17571
17572
    The library uses the following mapping from JSON values types to
17573
    UBJSON types according to the UBJSON specification:
17574
17575
    JSON value type | value/range                       | UBJSON type | marker
17576
    --------------- | --------------------------------- | ----------- | ------
17577
    null            | `null`                            | null        | `Z`
17578
    boolean         | `true`                            | true        | `T`
17579
    boolean         | `false`                           | false       | `F`
17580
    number_integer  | -9223372036854775808..-2147483649 | int64       | `L`
17581
    number_integer  | -2147483648..-32769               | int32       | `l`
17582
    number_integer  | -32768..-129                      | int16       | `I`
17583
    number_integer  | -128..127                         | int8        | `i`
17584
    number_integer  | 128..255                          | uint8       | `U`
17585
    number_integer  | 256..32767                        | int16       | `I`
17586
    number_integer  | 32768..2147483647                 | int32       | `l`
17587
    number_integer  | 2147483648..9223372036854775807   | int64       | `L`
17588
    number_unsigned | 0..127                            | int8        | `i`
17589
    number_unsigned | 128..255                          | uint8       | `U`
17590
    number_unsigned | 256..32767                        | int16       | `I`
17591
    number_unsigned | 32768..2147483647                 | int32       | `l`
17592
    number_unsigned | 2147483648..9223372036854775807   | int64       | `L`
17593
    number_float    | *any value*                       | float64     | `D`
17594
    string          | *with shortest length indicator*  | string      | `S`
17595
    array           | *see notes on optimized format*   | array       | `[`
17596
    object          | *see notes on optimized format*   | map         | `{`
17597
17598
    @note The mapping is **complete** in the sense that any JSON value type
17599
          can be converted to a UBJSON value.
17600
17601
    @note The following values can **not** be converted to a UBJSON value:
17602
          - strings with more than 9223372036854775807 bytes (theoretical)
17603
          - unsigned integer numbers above 9223372036854775807
17604
17605
    @note The following markers are not used in the conversion:
17606
          - `Z`: no-op values are not created.
17607
          - `C`: single-byte strings are serialized with `S` markers.
17608
17609
    @note Any UBJSON output created @ref to_ubjson can be successfully parsed
17610
          by @ref from_ubjson.
17611
17612
    @note If NaN or Infinity are stored inside a JSON number, they are
17613
          serialized properly. This behavior differs from the @ref dump()
17614
          function which serializes NaN or Infinity to `null`.
17615
17616
    @note The optimized formats for containers are supported: Parameter
17617
          @a use_size adds size information to the beginning of a container and
17618
          removes the closing marker. Parameter @a use_type further checks
17619
          whether all elements of a container have the same type and adds the
17620
          type marker to the beginning of the container. The @a use_type
17621
          parameter must only be used together with @a use_size = true. Note
17622
          that @a use_size = true alone may result in larger representations -
17623
          the benefit of this parameter is that the receiving side is
17624
          immediately informed on the number of elements of the container.
17625
17626
    @param[in] j  JSON value to serialize
17627
    @param[in] use_size  whether to add size annotations to container types
17628
    @param[in] use_type  whether to add type annotations to container types
17629
                         (must be combined with @a use_size = true)
17630
    @return UBJSON serialization as byte vector
17631
17632
    @complexity Linear in the size of the JSON value @a j.
17633
17634
    @liveexample{The example shows the serialization of a JSON value to a byte
17635
    vector in UBJSON format.,to_ubjson}
17636
17637
    @sa http://ubjson.org
17638
    @sa @ref from_ubjson(detail::input_adapter, const bool strict) for the
17639
        analogous deserialization
17640
    @sa @ref to_cbor(const basic_json& for the related CBOR format
17641
    @sa @ref to_msgpack(const basic_json&) for the related MessagePack format
17642
17643
    @since version 3.1.0
17644
    */
17645
    static std::vector<uint8_t> to_ubjson(const basic_json& j,
17646
                                          const bool use_size = false,
17647
                                          const bool use_type = false)
17648
    {
17649
        std::vector<uint8_t> result;
17650
        to_ubjson(j, result, use_size, use_type);
17651
        return result;
17652
    }
17653
17654
    static void to_ubjson(const basic_json& j, detail::output_adapter<uint8_t> o,
17655
                          const bool use_size = false, const bool use_type = false)
17656
    {
17657
        binary_writer<uint8_t>(o).write_ubjson(j, use_size, use_type);
17658
    }
17659
17660
    static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
17661
                          const bool use_size = false, const bool use_type = false)
17662
    {
17663
        binary_writer<char>(o).write_ubjson(j, use_size, use_type);
17664
    }
17665
17666
    /*!
17667
    @brief create a JSON value from an input in CBOR format
17668
17669
    Deserializes a given input @a i to a JSON value using the CBOR (Concise
17670
    Binary Object Representation) serialization format.
17671
17672
    The library maps CBOR types to JSON value types as follows:
17673
17674
    CBOR type              | JSON value type | first byte
17675
    ---------------------- | --------------- | ----------
17676
    Integer                | number_unsigned | 0x00..0x17
17677
    Unsigned integer       | number_unsigned | 0x18
17678
    Unsigned integer       | number_unsigned | 0x19
17679
    Unsigned integer       | number_unsigned | 0x1A
17680
    Unsigned integer       | number_unsigned | 0x1B
17681
    Negative integer       | number_integer  | 0x20..0x37
17682
    Negative integer       | number_integer  | 0x38
17683
    Negative integer       | number_integer  | 0x39
17684
    Negative integer       | number_integer  | 0x3A
17685
    Negative integer       | number_integer  | 0x3B
17686
    Negative integer       | number_integer  | 0x40..0x57
17687
    UTF-8 string           | string          | 0x60..0x77
17688
    UTF-8 string           | string          | 0x78
17689
    UTF-8 string           | string          | 0x79
17690
    UTF-8 string           | string          | 0x7A
17691
    UTF-8 string           | string          | 0x7B
17692
    UTF-8 string           | string          | 0x7F
17693
    array                  | array           | 0x80..0x97
17694
    array                  | array           | 0x98
17695
    array                  | array           | 0x99
17696
    array                  | array           | 0x9A
17697
    array                  | array           | 0x9B
17698
    array                  | array           | 0x9F
17699
    map                    | object          | 0xA0..0xB7
17700
    map                    | object          | 0xB8
17701
    map                    | object          | 0xB9
17702
    map                    | object          | 0xBA
17703
    map                    | object          | 0xBB
17704
    map                    | object          | 0xBF
17705
    False                  | `false`         | 0xF4
17706
    True                   | `true`          | 0xF5
17707
    Nill                   | `null`          | 0xF6
17708
    Half-Precision Float   | number_float    | 0xF9
17709
    Single-Precision Float | number_float    | 0xFA
17710
    Double-Precision Float | number_float    | 0xFB
17711
17712
    @warning The mapping is **incomplete** in the sense that not all CBOR
17713
             types can be converted to a JSON value. The following CBOR types
17714
             are not supported and will yield parse errors (parse_error.112):
17715
             - byte strings (0x40..0x5F)
17716
             - date/time (0xC0..0xC1)
17717
             - bignum (0xC2..0xC3)
17718
             - decimal fraction (0xC4)
17719
             - bigfloat (0xC5)
17720
             - tagged items (0xC6..0xD4, 0xD8..0xDB)
17721
             - expected conversions (0xD5..0xD7)
17722
             - simple values (0xE0..0xF3, 0xF8)
17723
             - undefined (0xF7)
17724
17725
    @warning CBOR allows map keys of any type, whereas JSON only allows
17726
             strings as keys in object values. Therefore, CBOR maps with keys
17727
             other than UTF-8 strings are rejected (parse_error.113).
17728
17729
    @note Any CBOR output created @ref to_cbor can be successfully parsed by
17730
          @ref from_cbor.
17731
17732
    @param[in] i  an input in CBOR format convertible to an input adapter
17733
    @param[in] strict  whether to expect the input to be consumed until EOF
17734
                       (true by default)
17735
    @param[in] allow_exceptions  whether to throw exceptions in case of a
17736
    parse error (optional, true by default)
17737
17738
    @return deserialized JSON value
17739
17740
    @throw parse_error.110 if the given input ends prematurely or the end of
17741
    file was not reached when @a strict was set to true
17742
    @throw parse_error.112 if unsupported features from CBOR were
17743
    used in the given input @a v or if the input is not valid CBOR
17744
    @throw parse_error.113 if a string was expected as map key, but not found
17745
17746
    @complexity Linear in the size of the input @a i.
17747
17748
    @liveexample{The example shows the deserialization of a byte vector in CBOR
17749
    format to a JSON value.,from_cbor}
17750
17751
    @sa http://cbor.io
17752
    @sa @ref to_cbor(const basic_json&) for the analogous serialization
17753
    @sa @ref from_msgpack(detail::input_adapter, const bool, const bool) for the
17754
        related MessagePack format
17755
    @sa @ref from_ubjson(detail::input_adapter, const bool, const bool) for the
17756
        related UBJSON format
17757
17758
    @since version 2.0.9; parameter @a start_index since 2.1.1; changed to
17759
           consume input adapters, removed start_index parameter, and added
17760
           @a strict parameter since 3.0.0; added @allow_exceptions parameter
17761
           since 3.2.0
17762
    */
17763
    static basic_json from_cbor(detail::input_adapter&& i,
17764
                                const bool strict = true,
17765
                                const bool allow_exceptions = true)
17766
    {
17767
        basic_json result;
17768
        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
17769
        const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::cbor, &sdp, strict);
17770
        return res ? result : basic_json(value_t::discarded);
17771
    }
17772
17773
    /*!
17774
    @copydoc from_cbor(detail::input_adapter, const bool, const bool)
17775
    */
17776
    template<typename A1, typename A2,
17777
             detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
17778
    static basic_json from_cbor(A1 && a1, A2 && a2,
17779
                                const bool strict = true,
17780
                                const bool allow_exceptions = true)
17781
    {
17782
        basic_json result;
17783
        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
17784
        const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::cbor, &sdp, strict);
17785
        return res ? result : basic_json(value_t::discarded);
17786
    }
17787
17788
    /*!
17789
    @brief create a JSON value from an input in MessagePack format
17790
17791
    Deserializes a given input @a i to a JSON value using the MessagePack
17792
    serialization format.
17793
17794
    The library maps MessagePack types to JSON value types as follows:
17795
17796
    MessagePack type | JSON value type | first byte
17797
    ---------------- | --------------- | ----------
17798
    positive fixint  | number_unsigned | 0x00..0x7F
17799
    fixmap           | object          | 0x80..0x8F
17800
    fixarray         | array           | 0x90..0x9F
17801
    fixstr           | string          | 0xA0..0xBF
17802
    nil              | `null`          | 0xC0
17803
    false            | `false`         | 0xC2
17804
    true             | `true`          | 0xC3
17805
    float 32         | number_float    | 0xCA
17806
    float 64         | number_float    | 0xCB
17807
    uint 8           | number_unsigned | 0xCC
17808
    uint 16          | number_unsigned | 0xCD
17809
    uint 32          | number_unsigned | 0xCE
17810
    uint 64          | number_unsigned | 0xCF
17811
    int 8            | number_integer  | 0xD0
17812
    int 16           | number_integer  | 0xD1
17813
    int 32           | number_integer  | 0xD2
17814
    int 64           | number_integer  | 0xD3
17815
    str 8            | string          | 0xD9
17816
    str 16           | string          | 0xDA
17817
    str 32           | string          | 0xDB
17818
    array 16         | array           | 0xDC
17819
    array 32         | array           | 0xDD
17820
    map 16           | object          | 0xDE
17821
    map 32           | object          | 0xDF
17822
    negative fixint  | number_integer  | 0xE0-0xFF
17823
17824
    @warning The mapping is **incomplete** in the sense that not all
17825
             MessagePack types can be converted to a JSON value. The following
17826
             MessagePack types are not supported and will yield parse errors:
17827
              - bin 8 - bin 32 (0xC4..0xC6)
17828
              - ext 8 - ext 32 (0xC7..0xC9)
17829
              - fixext 1 - fixext 16 (0xD4..0xD8)
17830
17831
    @note Any MessagePack output created @ref to_msgpack can be successfully
17832
          parsed by @ref from_msgpack.
17833
17834
    @param[in] i  an input in MessagePack format convertible to an input
17835
                  adapter
17836
    @param[in] strict  whether to expect the input to be consumed until EOF
17837
                       (true by default)
17838
    @param[in] allow_exceptions  whether to throw exceptions in case of a
17839
    parse error (optional, true by default)
17840
17841
    @return deserialized JSON value
17842
17843
    @throw parse_error.110 if the given input ends prematurely or the end of
17844
    file was not reached when @a strict was set to true
17845
    @throw parse_error.112 if unsupported features from MessagePack were
17846
    used in the given input @a i or if the input is not valid MessagePack
17847
    @throw parse_error.113 if a string was expected as map key, but not found
17848
17849
    @complexity Linear in the size of the input @a i.
17850
17851
    @liveexample{The example shows the deserialization of a byte vector in
17852
    MessagePack format to a JSON value.,from_msgpack}
17853
17854
    @sa http://msgpack.org
17855
    @sa @ref to_msgpack(const basic_json&) for the analogous serialization
17856
    @sa @ref from_cbor(detail::input_adapter, const bool, const bool) for the
17857
        related CBOR format
17858
    @sa @ref from_ubjson(detail::input_adapter, const bool, const bool) for
17859
        the related UBJSON format
17860
17861
    @since version 2.0.9; parameter @a start_index since 2.1.1; changed to
17862
           consume input adapters, removed start_index parameter, and added
17863
           @a strict parameter since 3.0.0; added @allow_exceptions parameter
17864
           since 3.2.0
17865
    */
17866
    static basic_json from_msgpack(detail::input_adapter&& i,
17867
                                   const bool strict = true,
17868
                                   const bool allow_exceptions = true)
17869
    {
17870
        basic_json result;
17871
        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
17872
        const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::msgpack, &sdp, strict);
17873
        return res ? result : basic_json(value_t::discarded);
17874
    }
17875
17876
    /*!
17877
    @copydoc from_msgpack(detail::input_adapter, const bool, const bool)
17878
    */
17879
    template<typename A1, typename A2,
17880
             detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
17881
    static basic_json from_msgpack(A1 && a1, A2 && a2,
17882
                                   const bool strict = true,
17883
                                   const bool allow_exceptions = true)
17884
    {
17885
        basic_json result;
17886
        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
17887
        const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::msgpack, &sdp, strict);
17888
        return res ? result : basic_json(value_t::discarded);
17889
    }
17890
17891
    /*!
17892
    @brief create a JSON value from an input in UBJSON format
17893
17894
    Deserializes a given input @a i to a JSON value using the UBJSON (Universal
17895
    Binary JSON) serialization format.
17896
17897
    The library maps UBJSON types to JSON value types as follows:
17898
17899
    UBJSON type | JSON value type                         | marker
17900
    ----------- | --------------------------------------- | ------
17901
    no-op       | *no value, next value is read*          | `N`
17902
    null        | `null`                                  | `Z`
17903
    false       | `false`                                 | `F`
17904
    true        | `true`                                  | `T`
17905
    float32     | number_float                            | `d`
17906
    float64     | number_float                            | `D`
17907
    uint8       | number_unsigned                         | `U`
17908
    int8        | number_integer                          | `i`
17909
    int16       | number_integer                          | `I`
17910
    int32       | number_integer                          | `l`
17911
    int64       | number_integer                          | `L`
17912
    string      | string                                  | `S`
17913
    char        | string                                  | `C`
17914
    array       | array (optimized values are supported)  | `[`
17915
    object      | object (optimized values are supported) | `{`
17916
17917
    @note The mapping is **complete** in the sense that any UBJSON value can
17918
          be converted to a JSON value.
17919
17920
    @param[in] i  an input in UBJSON format convertible to an input adapter
17921
    @param[in] strict  whether to expect the input to be consumed until EOF
17922
                       (true by default)
17923
    @param[in] allow_exceptions  whether to throw exceptions in case of a
17924
    parse error (optional, true by default)
17925
17926
    @return deserialized JSON value
17927
17928
    @throw parse_error.110 if the given input ends prematurely or the end of
17929
    file was not reached when @a strict was set to true
17930
    @throw parse_error.112 if a parse error occurs
17931
    @throw parse_error.113 if a string could not be parsed successfully
17932
17933
    @complexity Linear in the size of the input @a i.
17934
17935
    @liveexample{The example shows the deserialization of a byte vector in
17936
    UBJSON format to a JSON value.,from_ubjson}
17937
17938
    @sa http://ubjson.org
17939
    @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
17940
             analogous serialization
17941
    @sa @ref from_cbor(detail::input_adapter, const bool, const bool) for the
17942
        related CBOR format
17943
    @sa @ref from_msgpack(detail::input_adapter, const bool, const bool) for
17944
        the related MessagePack format
17945
17946
    @since version 3.1.0; added @allow_exceptions parameter since 3.2.0
17947
    */
17948
    static basic_json from_ubjson(detail::input_adapter&& i,
17949
                                  const bool strict = true,
17950
                                  const bool allow_exceptions = true)
17951
    {
17952
        basic_json result;
17953
        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
17954
        const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::ubjson, &sdp, strict);
17955
        return res ? result : basic_json(value_t::discarded);
17956
    }
17957
17958
    /*!
17959
    @copydoc from_ubjson(detail::input_adapter, const bool, const bool)
17960
    */
17961
    template<typename A1, typename A2,
17962
             detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
17963
    static basic_json from_ubjson(A1 && a1, A2 && a2,
17964
                                  const bool strict = true,
17965
                                  const bool allow_exceptions = true)
17966
    {
17967
        basic_json result;
17968
        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
17969
        const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::ubjson, &sdp, strict);
17970
        return res ? result : basic_json(value_t::discarded);
17971
    }
17972
17973
    /// @}
17974
17975
    //////////////////////////
17976
    // JSON Pointer support //
17977
    //////////////////////////
17978
17979
    /// @name JSON Pointer functions
17980
    /// @{
17981
17982
    /*!
17983
    @brief access specified element via JSON Pointer
17984
17985
    Uses a JSON pointer to retrieve a reference to the respective JSON value.
17986
    No bound checking is performed. Similar to @ref operator[](const typename
17987
    object_t::key_type&), `null` values are created in arrays and objects if
17988
    necessary.
17989
17990
    In particular:
17991
    - If the JSON pointer points to an object key that does not exist, it
17992
      is created an filled with a `null` value before a reference to it
17993
      is returned.
17994
    - If the JSON pointer points to an array index that does not exist, it
17995
      is created an filled with a `null` value before a reference to it
17996
      is returned. All indices between the current maximum and the given
17997
      index are also filled with `null`.
17998
    - The special value `-` is treated as a synonym for the index past the
17999
      end.
18000
18001
    @param[in] ptr  a JSON pointer
18002
18003
    @return reference to the element pointed to by @a ptr
18004
18005
    @complexity Constant.
18006
18007
    @throw parse_error.106   if an array index begins with '0'
18008
    @throw parse_error.109   if an array index was not a number
18009
    @throw out_of_range.404  if the JSON pointer can not be resolved
18010
18011
    @liveexample{The behavior is shown in the example.,operatorjson_pointer}
18012
18013
    @since version 2.0.0
18014
    */
18015
    reference operator[](const json_pointer& ptr)
18016
    {
18017
        return ptr.get_unchecked(this);
18018
    }
18019
18020
    /*!
18021
    @brief access specified element via JSON Pointer
18022
18023
    Uses a JSON pointer to retrieve a reference to the respective JSON value.
18024
    No bound checking is performed. The function does not change the JSON
18025
    value; no `null` values are created. In particular, the the special value
18026
    `-` yields an exception.
18027
18028
    @param[in] ptr  JSON pointer to the desired element
18029
18030
    @return const reference to the element pointed to by @a ptr
18031
18032
    @complexity Constant.
18033
18034
    @throw parse_error.106   if an array index begins with '0'
18035
    @throw parse_error.109   if an array index was not a number
18036
    @throw out_of_range.402  if the array index '-' is used
18037
    @throw out_of_range.404  if the JSON pointer can not be resolved
18038
18039
    @liveexample{The behavior is shown in the example.,operatorjson_pointer_const}
18040
18041
    @since version 2.0.0
18042
    */
18043
    const_reference operator[](const json_pointer& ptr) const
18044
    {
18045
        return ptr.get_unchecked(this);
18046
    }
18047
18048
    /*!
18049
    @brief access specified element via JSON Pointer
18050
18051
    Returns a reference to the element at with specified JSON pointer @a ptr,
18052
    with bounds checking.
18053
18054
    @param[in] ptr  JSON pointer to the desired element
18055
18056
    @return reference to the element pointed to by @a ptr
18057
18058
    @throw parse_error.106 if an array index in the passed JSON pointer @a ptr
18059
    begins with '0'. See example below.
18060
18061
    @throw parse_error.109 if an array index in the passed JSON pointer @a ptr
18062
    is not a number. See example below.
18063
18064
    @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr
18065
    is out of range. See example below.
18066
18067
    @throw out_of_range.402 if the array index '-' is used in the passed JSON
18068
    pointer @a ptr. As `at` provides checked access (and no elements are
18069
    implicitly inserted), the index '-' is always invalid. See example below.
18070
18071
    @throw out_of_range.403 if the JSON pointer describes a key of an object
18072
    which cannot be found. See example below.
18073
18074
    @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved.
18075
    See example below.
18076
18077
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
18078
    changes in the JSON value.
18079
18080
    @complexity Constant.
18081
18082
    @since version 2.0.0
18083
18084
    @liveexample{The behavior is shown in the example.,at_json_pointer}
18085
    */
18086
    reference at(const json_pointer& ptr)
18087
    {
18088
        return ptr.get_checked(this);
18089
    }
18090
18091
    /*!
18092
    @brief access specified element via JSON Pointer
18093
18094
    Returns a const reference to the element at with specified JSON pointer @a
18095
    ptr, with bounds checking.
18096
18097
    @param[in] ptr  JSON pointer to the desired element
18098
18099
    @return reference to the element pointed to by @a ptr
18100
18101
    @throw parse_error.106 if an array index in the passed JSON pointer @a ptr
18102
    begins with '0'. See example below.
18103
18104
    @throw parse_error.109 if an array index in the passed JSON pointer @a ptr
18105
    is not a number. See example below.
18106
18107
    @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr
18108
    is out of range. See example below.
18109
18110
    @throw out_of_range.402 if the array index '-' is used in the passed JSON
18111
    pointer @a ptr. As `at` provides checked access (and no elements are
18112
    implicitly inserted), the index '-' is always invalid. See example below.
18113
18114
    @throw out_of_range.403 if the JSON pointer describes a key of an object
18115
    which cannot be found. See example below.
18116
18117
    @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved.
18118
    See example below.
18119
18120
    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
18121
    changes in the JSON value.
18122
18123
    @complexity Constant.
18124
18125
    @since version 2.0.0
18126
18127
    @liveexample{The behavior is shown in the example.,at_json_pointer_const}
18128
    */
18129
    const_reference at(const json_pointer& ptr) const
18130
    {
18131
        return ptr.get_checked(this);
18132
    }
18133
18134
    /*!
18135
    @brief return flattened JSON value
18136
18137
    The function creates a JSON object whose keys are JSON pointers (see [RFC
18138
    6901](https://tools.ietf.org/html/rfc6901)) and whose values are all
18139
    primitive. The original JSON value can be restored using the @ref
18140
    unflatten() function.
18141
18142
    @return an object that maps JSON pointers to primitive values
18143
18144
    @note Empty objects and arrays are flattened to `null` and will not be
18145
          reconstructed correctly by the @ref unflatten() function.
18146
18147
    @complexity Linear in the size the JSON value.
18148
18149
    @liveexample{The following code shows how a JSON object is flattened to an
18150
    object whose keys consist of JSON pointers.,flatten}
18151
18152
    @sa @ref unflatten() for the reverse function
18153
18154
    @since version 2.0.0
18155
    */
18156
    basic_json flatten() const
18157
    {
18158
        basic_json result(value_t::object);
18159
        json_pointer::flatten("", *this, result);
18160
        return result;
18161
    }
18162
18163
    /*!
18164
    @brief unflatten a previously flattened JSON value
18165
18166
    The function restores the arbitrary nesting of a JSON value that has been
18167
    flattened before using the @ref flatten() function. The JSON value must
18168
    meet certain constraints:
18169
    1. The value must be an object.
18170
    2. The keys must be JSON pointers (see
18171
       [RFC 6901](https://tools.ietf.org/html/rfc6901))
18172
    3. The mapped values must be primitive JSON types.
18173
18174
    @return the original JSON from a flattened version
18175
18176
    @note Empty objects and arrays are flattened by @ref flatten() to `null`
18177
          values and can not unflattened to their original type. Apart from
18178
          this example, for a JSON value `j`, the following is always true:
18179
          `j == j.flatten().unflatten()`.
18180
18181
    @complexity Linear in the size the JSON value.
18182
18183
    @throw type_error.314  if value is not an object
18184
    @throw type_error.315  if object values are not primitive
18185
18186
    @liveexample{The following code shows how a flattened JSON object is
18187
    unflattened into the original nested JSON object.,unflatten}
18188
18189
    @sa @ref flatten() for the reverse function
18190
18191
    @since version 2.0.0
18192
    */
18193
    basic_json unflatten() const
18194
    {
18195
        return json_pointer::unflatten(*this);
18196
    }
18197
18198
    /// @}
18199
18200
    //////////////////////////
18201
    // JSON Patch functions //
18202
    //////////////////////////
18203
18204
    /// @name JSON Patch functions
18205
    /// @{
18206
18207
    /*!
18208
    @brief applies a JSON patch
18209
18210
    [JSON Patch](http://jsonpatch.com) defines a JSON document structure for
18211
    expressing a sequence of operations to apply to a JSON) document. With
18212
    this function, a JSON Patch is applied to the current JSON value by
18213
    executing all operations from the patch.
18214
18215
    @param[in] json_patch  JSON patch document
18216
    @return patched document
18217
18218
    @note The application of a patch is atomic: Either all operations succeed
18219
          and the patched document is returned or an exception is thrown. In
18220
          any case, the original value is not changed: the patch is applied
18221
          to a copy of the value.
18222
18223
    @throw parse_error.104 if the JSON patch does not consist of an array of
18224
    objects
18225
18226
    @throw parse_error.105 if the JSON patch is malformed (e.g., mandatory
18227
    attributes are missing); example: `"operation add must have member path"`
18228
18229
    @throw out_of_range.401 if an array index is out of range.
18230
18231
    @throw out_of_range.403 if a JSON pointer inside the patch could not be
18232
    resolved successfully in the current JSON value; example: `"key baz not
18233
    found"`
18234
18235
    @throw out_of_range.405 if JSON pointer has no parent ("add", "remove",
18236
    "move")
18237
18238
    @throw other_error.501 if "test" operation was unsuccessful
18239
18240
    @complexity Linear in the size of the JSON value and the length of the
18241
    JSON patch. As usually only a fraction of the JSON value is affected by
18242
    the patch, the complexity can usually be neglected.
18243
18244
    @liveexample{The following code shows how a JSON patch is applied to a
18245
    value.,patch}
18246
18247
    @sa @ref diff -- create a JSON patch by comparing two JSON values
18248
18249
    @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902)
18250
    @sa [RFC 6901 (JSON Pointer)](https://tools.ietf.org/html/rfc6901)
18251
18252
    @since version 2.0.0
18253
    */
18254
    basic_json patch(const basic_json& json_patch) const
18255
    {
18256
        // make a working copy to apply the patch to
18257
        basic_json result = *this;
18258
18259
        // the valid JSON Patch operations
18260
        enum class patch_operations {add, remove, replace, move, copy, test, invalid};
18261
18262
        const auto get_op = [](const std::string & op)
18263
        {
18264
            if (op == "add")
18265
            {
18266
                return patch_operations::add;
18267
            }
18268
            if (op == "remove")
18269
            {
18270
                return patch_operations::remove;
18271
            }
18272
            if (op == "replace")
18273
            {
18274
                return patch_operations::replace;
18275
            }
18276
            if (op == "move")
18277
            {
18278
                return patch_operations::move;
18279
            }
18280
            if (op == "copy")
18281
            {
18282
                return patch_operations::copy;
18283
            }
18284
            if (op == "test")
18285
            {
18286
                return patch_operations::test;
18287
            }
18288
18289
            return patch_operations::invalid;
18290
        };
18291
18292
        // wrapper for "add" operation; add value at ptr
18293
        const auto operation_add = [&result](json_pointer & ptr, basic_json val)
18294
        {
18295
            // adding to the root of the target document means replacing it
18296
            if (ptr.is_root())
18297
            {
18298
                result = val;
18299
            }
18300
            else
18301
            {
18302
                // make sure the top element of the pointer exists
18303
                json_pointer top_pointer = ptr.top();
18304
                if (top_pointer != ptr)
18305
                {
18306
                    result.at(top_pointer);
18307
                }
18308
18309
                // get reference to parent of JSON pointer ptr
18310
                const auto last_path = ptr.pop_back();
18311
                basic_json& parent = result[ptr];
18312
18313
                switch (parent.m_type)
18314
                {
18315
                    case value_t::null:
18316
                    case value_t::object:
18317
                    {
18318
                        // use operator[] to add value
18319
                        parent[last_path] = val;
18320
                        break;
18321
                    }
18322
18323
                    case value_t::array:
18324
                    {
18325
                        if (last_path == "-")
18326
                        {
18327
                            // special case: append to back
18328
                            parent.push_back(val);
18329
                        }
18330
                        else
18331
                        {
18332
                            const auto idx = json_pointer::array_index(last_path);
18333
                            if (JSON_UNLIKELY(static_cast<size_type>(idx) > parent.size()))
18334
                            {
18335
                                // avoid undefined behavior
18336
                                JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
18337
                            }
18338
                            else
18339
                            {
18340
                                // default case: insert add offset
18341
                                parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
18342
                            }
18343
                        }
18344
                        break;
18345
                    }
18346
18347
                    // LCOV_EXCL_START
18348
                    default:
18349
                    {
18350
                        // if there exists a parent it cannot be primitive
18351
                        assert(false);
18352
                    }
18353
                        // LCOV_EXCL_STOP
18354
                }
18355
            }
18356
        };
18357
18358
        // wrapper for "remove" operation; remove value at ptr
18359
        const auto operation_remove = [&result](json_pointer & ptr)
18360
        {
18361
            // get reference to parent of JSON pointer ptr
18362
            const auto last_path = ptr.pop_back();
18363
            basic_json& parent = result.at(ptr);
18364
18365
            // remove child
18366
            if (parent.is_object())
18367
            {
18368
                // perform range check
18369
                auto it = parent.find(last_path);
18370
                if (JSON_LIKELY(it != parent.end()))
18371
                {
18372
                    parent.erase(it);
18373
                }
18374
                else
18375
                {
18376
                    JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found"));
18377
                }
18378
            }
18379
            else if (parent.is_array())
18380
            {
18381
                // note erase performs range check
18382
                parent.erase(static_cast<size_type>(json_pointer::array_index(last_path)));
18383
            }
18384
        };
18385
18386
        // type check: top level value must be an array
18387
        if (JSON_UNLIKELY(not json_patch.is_array()))
18388
        {
18389
            JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects"));
18390
        }
18391
18392
        // iterate and apply the operations
18393
        for (const auto& val : json_patch)
18394
        {
18395
            // wrapper to get a value for an operation
18396
            const auto get_value = [&val](const std::string & op,
18397
                                          const std::string & member,
18398
                                          bool string_type) -> basic_json &
18399
            {
18400
                // find value
18401
                auto it = val.m_value.object->find(member);
18402
18403
                // context-sensitive error message
18404
                const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
18405
18406
                // check if desired value is present
18407
                if (JSON_UNLIKELY(it == val.m_value.object->end()))
18408
                {
18409
                    JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'"));
18410
                }
18411
18412
                // check if result is of type string
18413
                if (JSON_UNLIKELY(string_type and not it->second.is_string()))
18414
                {
18415
                    JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'"));
18416
                }
18417
18418
                // no error: return value
18419
                return it->second;
18420
            };
18421
18422
            // type check: every element of the array must be an object
18423
            if (JSON_UNLIKELY(not val.is_object()))
18424
            {
18425
                JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects"));
18426
            }
18427
18428
            // collect mandatory members
18429
            const std::string op = get_value("op", "op", true);
18430
            const std::string path = get_value(op, "path", true);
18431
            json_pointer ptr(path);
18432
18433
            switch (get_op(op))
18434
            {
18435
                case patch_operations::add:
18436
                {
18437
                    operation_add(ptr, get_value("add", "value", false));
18438
                    break;
18439
                }
18440
18441
                case patch_operations::remove:
18442
                {
18443
                    operation_remove(ptr);
18444
                    break;
18445
                }
18446
18447
                case patch_operations::replace:
18448
                {
18449
                    // the "path" location must exist - use at()
18450
                    result.at(ptr) = get_value("replace", "value", false);
18451
                    break;
18452
                }
18453
18454
                case patch_operations::move:
18455
                {
18456
                    const std::string from_path = get_value("move", "from", true);
18457
                    json_pointer from_ptr(from_path);
18458
18459
                    // the "from" location must exist - use at()
18460
                    basic_json v = result.at(from_ptr);
18461
18462
                    // The move operation is functionally identical to a
18463
                    // "remove" operation on the "from" location, followed
18464
                    // immediately by an "add" operation at the target
18465
                    // location with the value that was just removed.
18466
                    operation_remove(from_ptr);
18467
                    operation_add(ptr, v);
18468
                    break;
18469
                }
18470
18471
                case patch_operations::copy:
18472
                {
18473
                    const std::string from_path = get_value("copy", "from", true);
18474
                    const json_pointer from_ptr(from_path);
18475
18476
                    // the "from" location must exist - use at()
18477
                    basic_json v = result.at(from_ptr);
18478
18479
                    // The copy is functionally identical to an "add"
18480
                    // operation at the target location using the value
18481
                    // specified in the "from" member.
18482
                    operation_add(ptr, v);
18483
                    break;
18484
                }
18485
18486
                case patch_operations::test:
18487
                {
18488
                    bool success = false;
18489
                    JSON_TRY
18490
                    {
18491
                        // check if "value" matches the one at "path"
18492
                        // the "path" location must exist - use at()
18493
                        success = (result.at(ptr) == get_value("test", "value", false));
18494
                    }
18495
                    JSON_INTERNAL_CATCH (out_of_range&)
18496
                    {
18497
                        // ignore out of range errors: success remains false
18498
                    }
18499
18500
                    // throw an exception if test fails
18501
                    if (JSON_UNLIKELY(not success))
18502
                    {
18503
                        JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump()));
18504
                    }
18505
18506
                    break;
18507
                }
18508
18509
                case patch_operations::invalid:
18510
                {
18511
                    // op must be "add", "remove", "replace", "move", "copy", or
18512
                    // "test"
18513
                    JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid"));
18514
                }
18515
            }
18516
        }
18517
18518
        return result;
18519
    }
18520
18521
    /*!
18522
    @brief creates a diff as a JSON patch
18523
18524
    Creates a [JSON Patch](http://jsonpatch.com) so that value @a source can
18525
    be changed into the value @a target by calling @ref patch function.
18526
18527
    @invariant For two JSON values @a source and @a target, the following code
18528
    yields always `true`:
18529
    @code {.cpp}
18530
    source.patch(diff(source, target)) == target;
18531
    @endcode
18532
18533
    @note Currently, only `remove`, `add`, and `replace` operations are
18534
          generated.
18535
18536
    @param[in] source  JSON value to compare from
18537
    @param[in] target  JSON value to compare against
18538
    @param[in] path    helper value to create JSON pointers
18539
18540
    @return a JSON patch to convert the @a source to @a target
18541
18542
    @complexity Linear in the lengths of @a source and @a target.
18543
18544
    @liveexample{The following code shows how a JSON patch is created as a
18545
    diff for two JSON values.,diff}
18546
18547
    @sa @ref patch -- apply a JSON patch
18548
    @sa @ref merge_patch -- apply a JSON Merge Patch
18549
18550
    @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902)
18551
18552
    @since version 2.0.0
18553
    */
18554
    static basic_json diff(const basic_json& source, const basic_json& target,
18555
                           const std::string& path = "")
18556
    {
18557
        // the patch
18558
        basic_json result(value_t::array);
18559
18560
        // if the values are the same, return empty patch
18561
        if (source == target)
18562
        {
18563
            return result;
18564
        }
18565
18566
        if (source.type() != target.type())
18567
        {
18568
            // different types: replace value
18569
            result.push_back(
18570
            {
18571
                {"op", "replace"}, {"path", path}, {"value", target}
18572
            });
18573
        }
18574
        else
18575
        {
18576
            switch (source.type())
18577
            {
18578
                case value_t::array:
18579
                {
18580
                    // first pass: traverse common elements
18581
                    std::size_t i = 0;
18582
                    while (i < source.size() and i < target.size())
18583
                    {
18584
                        // recursive call to compare array values at index i
18585
                        auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
18586
                        result.insert(result.end(), temp_diff.begin(), temp_diff.end());
18587
                        ++i;
18588
                    }
18589
18590
                    // i now reached the end of at least one array
18591
                    // in a second pass, traverse the remaining elements
18592
18593
                    // remove my remaining elements
18594
                    const auto end_index = static_cast<difference_type>(result.size());
18595
                    while (i < source.size())
18596
                    {
18597
                        // add operations in reverse order to avoid invalid
18598
                        // indices
18599
                        result.insert(result.begin() + end_index, object(
18600
                        {
18601
                            {"op", "remove"},
18602
                            {"path", path + "/" + std::to_string(i)}
18603
                        }));
18604
                        ++i;
18605
                    }
18606
18607
                    // add other remaining elements
18608
                    while (i < target.size())
18609
                    {
18610
                        result.push_back(
18611
                        {
18612
                            {"op", "add"},
18613
                            {"path", path + "/" + std::to_string(i)},
18614
                            {"value", target[i]}
18615
                        });
18616
                        ++i;
18617
                    }
18618
18619
                    break;
18620
                }
18621
18622
                case value_t::object:
18623
                {
18624
                    // first pass: traverse this object's elements
18625
                    for (auto it = source.cbegin(); it != source.cend(); ++it)
18626
                    {
18627
                        // escape the key name to be used in a JSON patch
18628
                        const auto key = json_pointer::escape(it.key());
18629
18630
                        if (target.find(it.key()) != target.end())
18631
                        {
18632
                            // recursive call to compare object values at key it
18633
                            auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key);
18634
                            result.insert(result.end(), temp_diff.begin(), temp_diff.end());
18635
                        }
18636
                        else
18637
                        {
18638
                            // found a key that is not in o -> remove it
18639
                            result.push_back(object(
18640
                            {
18641
                                {"op", "remove"}, {"path", path + "/" + key}
18642
                            }));
18643
                        }
18644
                    }
18645
18646
                    // second pass: traverse other object's elements
18647
                    for (auto it = target.cbegin(); it != target.cend(); ++it)
18648
                    {
18649
                        if (source.find(it.key()) == source.end())
18650
                        {
18651
                            // found a key that is not in this -> add it
18652
                            const auto key = json_pointer::escape(it.key());
18653
                            result.push_back(
18654
                            {
18655
                                {"op", "add"}, {"path", path + "/" + key},
18656
                                {"value", it.value()}
18657
                            });
18658
                        }
18659
                    }
18660
18661
                    break;
18662
                }
18663
18664
                default:
18665
                {
18666
                    // both primitive type: replace value
18667
                    result.push_back(
18668
                    {
18669
                        {"op", "replace"}, {"path", path}, {"value", target}
18670
                    });
18671
                    break;
18672
                }
18673
            }
18674
        }
18675
18676
        return result;
18677
    }
18678
18679
    /// @}
18680
18681
    ////////////////////////////////
18682
    // JSON Merge Patch functions //
18683
    ////////////////////////////////
18684
18685
    /// @name JSON Merge Patch functions
18686
    /// @{
18687
18688
    /*!
18689
    @brief applies a JSON Merge Patch
18690
18691
    The merge patch format is primarily intended for use with the HTTP PATCH
18692
    method as a means of describing a set of modifications to a target
18693
    resource's content. This function applies a merge patch to the current
18694
    JSON value.
18695
18696
    The function implements the following algorithm from Section 2 of
18697
    [RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396):
18698
18699
    ```
18700
    define MergePatch(Target, Patch):
18701
      if Patch is an Object:
18702
        if Target is not an Object:
18703
          Target = {} // Ignore the contents and set it to an empty Object
18704
        for each Name/Value pair in Patch:
18705
          if Value is null:
18706
            if Name exists in Target:
18707
              remove the Name/Value pair from Target
18708
          else:
18709
            Target[Name] = MergePatch(Target[Name], Value)
18710
        return Target
18711
      else:
18712
        return Patch
18713
    ```
18714
18715
    Thereby, `Target` is the current object; that is, the patch is applied to
18716
    the current value.
18717
18718
    @param[in] patch  the patch to apply
18719
18720
    @complexity Linear in the lengths of @a patch.
18721
18722
    @liveexample{The following code shows how a JSON Merge Patch is applied to
18723
    a JSON document.,merge_patch}
18724
18725
    @sa @ref patch -- apply a JSON patch
18726
    @sa [RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396)
18727
18728
    @since version 3.0.0
18729
    */
18730
    void merge_patch(const basic_json& patch)
18731
    {
18732
        if (patch.is_object())
18733
        {
18734
            if (not is_object())
18735
            {
18736
                *this = object();
18737
            }
18738
            for (auto it = patch.begin(); it != patch.end(); ++it)
18739
            {
18740
                if (it.value().is_null())
18741
                {
18742
                    erase(it.key());
18743
                }
18744
                else
18745
                {
18746
                    operator[](it.key()).merge_patch(it.value());
18747
                }
18748
            }
18749
        }
18750
        else
18751
        {
18752
            *this = patch;
18753
        }
18754
    }
18755
18756
    /// @}
18757
};
18758
} // namespace nlohmann
18759
18760
///////////////////////
18761
// nonmember support //
18762
///////////////////////
18763
18764
// specialization of std::swap, and std::hash
18765
namespace std
18766
{
18767
18768
/// hash value for JSON objects
18769
template<>
18770
struct hash<nlohmann::json>
18771
{
18772
    /*!
18773
    @brief return a hash value for a JSON object
18774
18775
    @since version 1.0.0
18776
    */
18777
    std::size_t operator()(const nlohmann::json& j) const
18778
0
    {
18779
0
        // a naive hashing via the string representation
18780
0
        const auto& h = hash<nlohmann::json::string_t>();
18781
0
        return h(j.dump());
18782
0
    }
18783
};
18784
18785
/// specialization for std::less<value_t>
18786
/// @note: do not remove the space after '<',
18787
///        see https://github.com/nlohmann/json/pull/679
18788
template<>
18789
struct less< ::nlohmann::detail::value_t>
18790
{
18791
    /*!
18792
    @brief compare two value_t enum values
18793
    @since version 3.0.0
18794
    */
18795
    bool operator()(nlohmann::detail::value_t lhs,
18796
                    nlohmann::detail::value_t rhs) const noexcept
18797
0
    {
18798
0
        return nlohmann::detail::operator<(lhs, rhs);
18799
0
    }
18800
};
18801
18802
/*!
18803
@brief exchanges the values of two JSON objects
18804
18805
@since version 1.0.0
18806
*/
18807
template<>
18808
inline void swap<nlohmann::json>(nlohmann::json& j1, nlohmann::json& j2) noexcept(
18809
    is_nothrow_move_constructible<nlohmann::json>::value and
18810
    is_nothrow_move_assignable<nlohmann::json>::value
18811
)
18812
0
{
18813
0
    j1.swap(j2);
18814
0
}
18815
18816
} // namespace std
18817
18818
/*!
18819
@brief user-defined string literal for JSON values
18820
18821
This operator implements a user-defined string literal for JSON objects. It
18822
can be used by adding `"_json"` to a string literal and returns a JSON object
18823
if no parse error occurred.
18824
18825
@param[in] s  a string representation of a JSON object
18826
@param[in] n  the length of string @a s
18827
@return a JSON object
18828
18829
@since version 1.0.0
18830
*/
18831
inline nlohmann::json operator "" _json(const char* s, std::size_t n)
18832
0
{
18833
0
    return nlohmann::json::parse(s, s + n);
18834
0
}
18835
18836
/*!
18837
@brief user-defined string literal for JSON pointer
18838
18839
This operator implements a user-defined string literal for JSON Pointers. It
18840
can be used by adding `"_json_pointer"` to a string literal and returns a JSON pointer
18841
object if no parse error occurred.
18842
18843
@param[in] s  a string representation of a JSON Pointer
18844
@param[in] n  the length of string @a s
18845
@return a JSON pointer object
18846
18847
@since version 2.0.0
18848
*/
18849
inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
18850
0
{
18851
0
    return nlohmann::json::json_pointer(std::string(s, n));
18852
0
}
18853
18854
// #include <nlohmann/detail/macro_unscope.hpp>
18855
18856
18857
// restore GCC/clang diagnostic settings
18858
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
18859
    #pragma GCC diagnostic pop
18860
#endif
18861
#if defined(__clang__)
18862
    #pragma GCC diagnostic pop
18863
#endif
18864
18865
// clean up
18866
#undef JSON_INTERNAL_CATCH
18867
#undef JSON_CATCH
18868
#undef JSON_THROW
18869
#undef JSON_TRY
18870
#undef JSON_LIKELY
18871
#undef JSON_UNLIKELY
18872
#undef JSON_DEPRECATED
18873
#undef JSON_HAS_CPP_14
18874
#undef JSON_HAS_CPP_17
18875
#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
18876
#undef NLOHMANN_BASIC_JSON_TPL
18877
18878
18879
#endif
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/menu_tree/menu_tree.cpp
Line
Count
Source (jump to first uncovered line)
1
#include "menu_tree.h"
2
3
menu_tree::menu_tree (const std::string &path, LCD_c *mainLCD_PTR):database_path(path),w_serial( "([Ss]\\d{1,3}[Ee]\\d{1,3})")
4
12
{
5
12
    mainLCD=mainLCD_PTR;
6
12
7
12
    i_stack.push(0);
8
12
    i=0;
9
12
    get_list(database_path);
10
12
}
11
12
bool menu_tree::is_file() const
13
7
{
14
7
    return movie_database_vector[i].is_file;
15
7
}
16
//std::string menu_tree::return_path( int i) const
17
//{
18
19
//    return movie_database_vector[i].path;
20
//}
21
22
//void menu_tree::get_main_list()
23
//{
24
//    get_list( database_path );
25
//}
26
void menu_tree::next()
27
23
{   
28
23
    ++i;
29
23
    if (get_vector_size() == i ){
30
2
        i=0;
31
2
    }
32
23
}
33
34
void menu_tree::previous()
35
6
{
36
6
    --i;
37
6
    if ( i <0 )
38
1
    {
39
1
        i=get_vector_size()-1;
40
1
    }
41
6
}
42
43
int menu_tree::get_vector_size () const
44
24
{
45
24
    return movie_database_vector.size();
46
24
}
47
void menu_tree::vector_clear ()
48
14
{
49
14
    movie_database_vector.clear();
50
14
}
51
int menu_tree::get_i()
52
1
{
53
1
    if (i_stack.size() >1 ) {
54
1
        int i = i_stack.top();
55
1
        i_stack.pop();
56
1
        return i;
57
1
    }
58
0
    else
59
0
        return 0;
60
1
}
61
62
void menu_tree::enter_dir()
63
1
{
64
1
    i_stack.push(i); // wpisuje na stos kolejna wersje licznika i
65
1
    
66
1
    if (movie_database_vector[i].is_file == true ) {
67
0
68
0
    }
69
1
    else {
70
1
        get_list (movie_database_vector[i].path);
71
1
        i=0;
72
1
    }
73
1
}
74
//void menu_tree::enter_dir(const std::string& path)
75
//{
76
//    get_list (path) ;
77
//}
78
79
void menu_tree::back_dir()
80
1
{
81
1
    if ( tree_stack.size() >1 ) {
82
1
        tree_stack.pop();
83
1
        std::string path = tree_stack.top();
84
1
        tree_stack.pop();
85
1
        i = get_i();
86
1
        get_list (path);
87
1
        return;
88
1
    }
89
0
    i = get_i();
90
0
    get_list (database_path);
91
0
    return;
92
0
}
93
94
std::string menu_tree::show_list()
95
60
{
96
60
    if (movie_database_vector[i].is_file == true ) {
97
40
        mainLCD->printString(true,0,0,movie_database_vector[i].files_name.substr(0,16));
98
40
99
40
        return movie_database_vector[i].files_name;
100
40
    }
101
20
    else {
102
20
        mainLCD->printString(true,0,0,movie_database_vector[i].files_name+" ->");
103
20
    }
104
60
105
60
    return movie_database_vector[i].path;
106
60
}
107
bool comper (const movie_database & a , const movie_database& b);
108
//{
109
//    return a.files_name < b.files_name;
110
//}
111
112
14
void menu_tree::get_list(const std::string& path) {
113
14
    tree_stack.push(path);
114
14
    vector_clear(); // czyscimy vector
115
14
    std::string path2(path);
116
14
    std::string v_path ,tmp_string;
117
14
    if(sciezka = opendir( path.c_str() )) {
118
13
119
13
120
104
        while(( plik = readdir( sciezka ) ) )
121
91
        {
122
91
            path2 =path;
123
91
            if (static_cast<int>(plik->d_type) == 4 /*&& strcmp( plik->d_name, "..") && strcmp( plik->d_name, ".")*/ )
124
52
            {
125
52
                if (!strcmp( plik->d_name, "..") || !strcmp( plik->d_name, "."))
126
26
                {continue;}
127
26
                temp.is_file=false;
128
26
            }
129
39
            else //if ( (int)plik->d_type == 8 && strcmp( plik->d_name, "..") && strcmp( plik->d_name, "."))
130
39
            {
131
39
                temp.is_file=true;
132
39
            }
133
91
134
91
            v_path= path2;
135
65
            v_path+="/";
136
65
            tmp_string.assign(plik->d_name);
137
65
            v_path+=tmp_string;
138
65
            temp.path =v_path;
139
65
            temp.files_name.assign(plik->d_name);
140
65
            movie_database_vector.push_back(temp);
141
65
142
65
        } // end while
143
13
        sort(movie_database_vector.begin(),movie_database_vector.end(), comper);
144
13
        closedir( sciezka );
145
13
    }
146
14
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDom_server_OOP.h
Line
Count
Source
1
#ifndef GLOBAL_H
2
#define GLOBAL_H
3
4
#include <iostream>
5
#include <fstream>
6
#include <string>
7
#include <cstdlib>
8
#include <pthread.h>
9
#include <stdio.h>
10
#include <stdlib.h>
11
#include <sys/socket.h>
12
#include <sys/types.h>
13
#include <netinet/in.h>
14
#include <vector>
15
#include <thread>
16
#include <arpa/inet.h>
17
#include <netinet/in.h>
18
#include <unistd.h>
19
#include <sys/fcntl.h>
20
#include <unistd.h>
21
#include <errno.h>
22
#include <signal.h>
23
#include <time.h>
24
#include <wiringPi.h>
25
#include <chrono>
26
#include <array>
27
28
// MOJE BIBLIOTEKI
29
#include "KEY/key.h"
30
#include "logger/logger.hpp"
31
#include "files_tree/files_tree.h"
32
#include "menu_tree/menu_tree.h"
33
#include "LCD_c/lcd_c.h"
34
#include "command/command.h"
35
#include "../libs/event_counters/event_counters_handler.h"
36
#include "iDomTools/idomtools.h"
37
#include "iDomStatus/idomstatus.h"
38
#include "iDomSaveState/idom_save_state.h"
39
40
56
#define log_file_cout  f_log //std::cout zmien f_log na std::cout i bedzie wypisywac na ekran
41
16
#define log_file_mutex f_log
42
43
enum class iDomStateEnum{
44
    CLOSE = 0,
45
    RELOAD,
46
    ERROR,
47
    WORKING,
48
    HARD_RELOAD
49
};
50
51
namespace iDomConst
52
{
53
constexpr int MAX_CONNECTION = 10;
54
constexpr int FREE  = 1;
55
constexpr int RS232 = 11;
56
constexpr int CLOCK = 12;
57
constexpr int ok    = 0;
58
constexpr int GPIO_SPIK = 21;
59
constexpr int GPIO_PRINTER = 22;
60
constexpr int BUTTON_PIN = 25;
61
}
62
struct ALERT
63
{
64
    Clock time;
65
    STATE state = STATE::DEACTIVE;
66
    unsigned int fromVolume = 48;
67
    unsigned int toVolume = 58;
68
    unsigned int radioID = 8;
69
};
70
71
extern std::string _logfile;
72
extern Logger log_file_mutex;
73
extern std::string buffer;
74
75
enum class TEMPERATURE_STATE;
76
enum class PILOT_KEY;
77
78
struct MPD_info{
79
    std::string title   = "NULL";
80
    std::string radio   = "NULL";
81
    std::string artist  = "NULL";
82
    int volume = 0;
83
    bool isPlay = false;
84
    int currentSongID = 0;
85
    std::vector <std::string> songList = {"NULL"};
86
};
87
struct s_pointer{
88
    unsigned int *ptr_who;
89
    int32_t *ptr_buf;
90
};
91
92
struct Thread_array_struc {
93
    std::thread thread;
94
    std::thread::id thread_ID = std::thread::id(0);
95
    std::string thread_name;
96
    int thread_socket = 0;
97
};
98
99
struct address_another_servers {
100
    int id;
101
    std::string SERVER_IP;
102
};
103
104
struct FTP_SERVER{
105
    std::string URL;
106
    std::string user;
107
    std::string pass;
108
};
109
struct iDOM_STATE{
110
    STATE houseState = STATE::UNDEFINE;
111
112
};
113
114
struct config{
115
    std::string portRS232;
116
    std::string portRS232_clock;
117
    std::string BaudRate;
118
    std::string RFLinkPort;
119
    std::string RFLinkBaudRate;
120
    int PORT;
121
    std::string SERVER_IP;
122
    std::string MPD_IP;
123
    std::string MOVIES_DB_PATH;
124
    std::string MENU_PATH;
125
    std::string THREAD_MPD   = "NULL";
126
    std::string THREAD_IRDA  = "NULL";
127
    std::string THREAD_CRON  = "NULL";
128
    std::string THREAD_RS232 = "NULL";
129
    std::string THREAD_DUMMY = "NULL";
130
    std::string TS_KEY= " gg ";
131
    std::string cameraLedON = "";
132
    std::string cameraLedOFF ="";
133
    std::string cameraURL="";
134
    std::string facebookAccessToken = "";
135
    std::string viberToken = "NULL";
136
    std::string viberAvatar;
137
    std::vector <std::string> viberReceiver;
138
    std::string viberSender;
139
    std::string radio433MHzConfigFile;
140
    std::string omxplayerFile = "NULL";
141
    int ID_server = 0;
142
    int v_delay;
143
    bool encrypted = true;
144
145
    FTP_SERVER ftpServer;
146
    std::string lightningApiURL = "NULL";
147
    std::string saveFilePath = "NULL";
148
};
149
150
struct LED_Strip{
151
    std::string from;
152
    std::string to;
153
    std::string R;
154
    std::string G;
155
    std::string B;
156
    std::string colorName;
157
158
    LED_Strip (int from, int to, int r, int g, int b, std::string colorName = "NULL"):from(std::to_string(from)),
159
        to(std::to_string(to)),
160
        R(std::to_string(r)),
161
        G(std::to_string(g)),
162
        B(std::to_string(b)),
163
        colorName(colorName)
164
1.55k
    {
165
1.55k
166
1.55k
    }
167
    LED_Strip (const std::string& from,
168
               const std::string& to,
169
               const std::string& r,
170
               const std::string& g,
171
               const std::string& b,
172
               const std::string& colorName = "NULL"):
173
        from(from),
174
        to(to),
175
        R(r),
176
        G(g),
177
        B(b),
178
        colorName(colorName)
179
    {
180
181
    }
182
183
    void set (const std::string& from,
184
              const std::string& to,
185
              const std::string& r,
186
              const std::string& g,
187
              const std::string& b,
188
              const std::string& colorName = "NULL")
189
    {
190
        this->from =from;
191
        this->to = to;
192
        R = r;
193
        G = g;
194
        B = b;
195
        this->colorName =colorName;
196
    }
197
198
    void set (int from, int to, int r, int g, int b, std::string colorName = "NULL"){
199
        this->from = std::to_string(from);
200
        this->to = std::to_string(to);
201
        R = std::to_string(r);
202
        G = std::to_string(g);
203
        B = std::to_string(b);
204
        this->colorName =colorName;
205
    }
206
207
    std::string getColorName() const{
208
        return colorName;
209
    }
210
211
    std::string get(unsigned int _from, unsigned int _to) const{
212
        if (_from != 0 || _to != 60){
213
            return "LED:["+std::to_string(_from)+"-"+std::to_string(_to)+"-"+R+"-"+G+"-"+B+"];";
214
        }
215
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
216
    }
217
218
    std::string makeCommand(const std::string& from,
219
                            const std::string& to,
220
                            const std::string& R,
221
                            const std::string& G,
222
                            const std::string& B){
223
        return "LED:["+from+"-"+to+"-"+R+"-"+G+"-"+B+"];";
224
    }
225
};
226
227
struct pilot_led{
228
    unsigned int counter=0;
229
    std::vector<LED_Strip> colorLED   = { LED_Strip(1,60,237,145,33 ,"carrot orange"),
230
                                          LED_Strip(1,60,255,0,0    ,"red"),
231
                                          LED_Strip(1,60,0,255,0    ,"green"),
232
                                          LED_Strip(1,60,0,0,255    ,"blue"),
233
                                          LED_Strip(1,60,255,255,255,"white"),
234
                                          LED_Strip(1,60,255,255,0  ,"yellow"),
235
                                          LED_Strip(1,60,0,255,255  ,"cyan"),
236
                                          LED_Strip(1,60,255,0,255  ,"magenta")
237
                                        };
238
};
239
240
class command; // for struc thread_data req
241
class iDomTOOLS;
242
class RADIO_EQ_CONTAINER;
243
class RFLinkHandler;
244
245
struct thread_data{
246
    int s_client_sock;
247
    struct sockaddr_in from;
248
    struct config *server_settings = NULL;
249
    struct s_pointer pointer;
250
    LCD_c *mainLCD = NULL;
251
    files_tree *main_tree = NULL;
252
    menu_tree *main_MENU = NULL;
253
    iDomTOOLS *main_iDomTools = NULL;
254
    RFLinkHandler *main_RFLink = NULL;
255
    std::array<Thread_array_struc, iDomConst::MAX_CONNECTION> *main_THREAD_arr = NULL;
256
    time_t start;
257
    time_t now_time;
258
    int sleeper;
259
    std::map <std::string, std::unique_ptr <KEY> > key_map;
260
    MPD_info *ptr_MPD_info = NULL;
261
    pilot_led * ptr_pilot_led = NULL;
262
    std::map <std::string, std::unique_ptr<command> >* commandMapPtr = NULL;
263
    event_counters_handler myEventHandler;
264
    std::string encriptionKey = "40%";
265
    iDomSTATUS *main_iDomStatus;
266
    iDOM_STATE idom_all_state;
267
    ALERT alarmTime;
268
    std::shared_ptr<RADIO_EQ_CONTAINER> main_REC;
269
    iDomStateEnum iDomProgramState = iDomStateEnum::WORKING;
270
};
271
272
struct thread_data_rs232{
273
    std::string portRS232;
274
    std::string portRS232_clock;
275
    std::string BaudRate;
276
    struct s_pointer pointer;
277
};
278
279
#endif // GLOBAL_H
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/thread_functions/TEST/rs232_thread_BT.cpp
Line
Count
Source
1
#include <gtest/gtest.h>
2
#include "../../iDom_server_OOP.h"
3
#include "../rs232_thread.h"
4
#include "test_data.h"
5
#include "../../../iDom_server_OOP/src/iDomTools/test/iDomTools_fixture.h"
6
7
std::mutex useful_F::mutex_buf;
8
std::mutex useful_F::mutex_who;
9
10
std::string buffer;
11
12
class rs232_thread_fixture : public iDomTOOLS_ClassTest
13
{
14
15
};
16
17
TEST_F(rs232_thread_fixture, send_Recieve_rs232_thread_fixture_clock)
18
1
{
19
1
    useful_F::go_while = true;
20
1
    EXPECT_EQ(useful_F::myStaticData->myEventHandler.run("RS232")->howManyEvent(), 0);
21
1
    thread_data_rs232 test_data_rs232;
22
1
    test_data_rs232.BaudRate = "9600";
23
1
    test_data_rs232.portRS232 = "test_port";
24
1
    test_data_rs232.portRS232_clock = "test_port_clock";
25
1
    unsigned int wh[2];
26
1
    test_data_rs232.pointer.ptr_who = wh;
27
1
    test_data_rs232.pointer.ptr_who[0] = iDomConst::CLOCK;
28
1
    test_data_rs232.pointer.ptr_who[1] = iDomConst::FREE;
29
1
    EXPECT_EQ(test_data_rs232.pointer.ptr_who[1], iDomConst::FREE);
30
1
31
1
    SerialPi_set_recv_msg("OK");
32
1
    EXPECT_STREQ(TEST_DATA::serial_b.c_str(),"OK");
33
1
    Send_Recieve_rs232_thread(&test_data_rs232,"RS232_THREAD");
34
1
35
1
    EXPECT_STREQ(TEST_DATA::serial_b.c_str(),"");
36
1
    EXPECT_EQ(test_data_rs232.pointer.ptr_who[1], iDomConst::CLOCK);
37
1
    EXPECT_EQ(useful_F::myStaticData->myEventHandler.run("RS232")->howManyEvent(), 0);
38
1
}
39
40
TEST_F(rs232_thread_fixture, send_Recieve_rs232_thread_clock_empty_answer)
41
1
{
42
1
    useful_F::go_while = true;
43
1
    thread_data_rs232 test_data_rs232;
44
1
    test_data_rs232.BaudRate = "9600";
45
1
    test_data_rs232.portRS232 = "test_port";
46
1
    test_data_rs232.portRS232_clock = "test_port_clock";
47
1
    unsigned int test_who[2] = {iDomConst::CLOCK, iDomConst::FREE};
48
1
    EXPECT_EQ(test_who[1], iDomConst::FREE);
49
1
    test_data_rs232.pointer.ptr_who = test_who;
50
1
    EXPECT_EQ(useful_F::myStaticData->myEventHandler.run("RS232")->howManyEvent(), 0);
51
1
    SerialPi_set_recv_msg("");
52
1
    EXPECT_STREQ(TEST_DATA::serial_b.c_str(),"");
53
1
    Send_Recieve_rs232_thread(&test_data_rs232, "RS232_thread");
54
1
55
1
    EXPECT_STREQ(TEST_DATA::serial_b.c_str(),"");
56
1
    EXPECT_EQ(test_data_rs232.pointer.ptr_who[1], iDomConst::CLOCK);
57
1
    EXPECT_EQ(useful_F::myStaticData->myEventHandler.run("RS232")->howManyEvent(), 1);
58
1
}
59
60
TEST_F(rs232_thread_fixture, send_Recieve_rs232_thread_RS232)
61
1
{
62
1
    useful_F::go_while = true;
63
1
    thread_data_rs232 test_data_rs232;
64
1
    test_data_rs232.BaudRate = "9600";
65
1
    test_data_rs232.portRS232 = "test_port";
66
1
    test_data_rs232.portRS232_clock = "test_port_clock";
67
1
    unsigned int test_who[2] = {iDomConst::RS232, iDomConst::FREE};
68
1
    test_data_rs232.pointer.ptr_who = test_who;
69
1
70
1
    test_data_rs232.pointer.ptr_who[0] = iDomConst::RS232;
71
1
    EXPECT_EQ(test_who[0], iDomConst::RS232);
72
1
    SerialPi_set_recv_msg("OK;");
73
1
    Send_Recieve_rs232_thread(&test_data_rs232,"RS232_thread");
74
1
75
1
    EXPECT_STREQ(TEST_DATA::serial_b.c_str(),"");
76
1
    EXPECT_EQ(test_who[1], iDomConst::RS232);
77
1
}
78
79
TEST_F(rs232_thread_fixture, send_Recieve_rs232_thread_FREE)
80
1
{
81
1
    EXPECT_EQ(useful_F::myStaticData->myEventHandler.run("RS232")->howManyEvent(), 0);
82
1
    useful_F::go_while = true;
83
1
    thread_data_rs232 test_data_rs232;
84
1
    test_data_rs232.BaudRate = "9600";
85
1
    test_data_rs232.portRS232 = "test_port";
86
1
    test_data_rs232.portRS232_clock = "test_port_clock";
87
1
    unsigned int test_who[2] = {iDomConst::FREE, iDomConst::FREE};
88
1
    test_data_rs232.pointer.ptr_who = test_who;
89
1
90
1
    test_data_rs232.pointer.ptr_who[0] = iDomConst::FREE;
91
1
    EXPECT_EQ(test_who[0], iDomConst::FREE);
92
1
    SerialPi_set_recv_msg("TEST;");
93
1
    Send_Recieve_rs232_thread(&test_data_rs232,"RS232_thread");
94
1
95
1
    EXPECT_STREQ(TEST_DATA::serial_b.c_str(),"");
96
1
    EXPECT_EQ(test_who[1], iDomConst::FREE);
97
1
    EXPECT_EQ(useful_F::myStaticData->myEventHandler.run("RS232")->howManyEvent(), 1);
98
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/RADIO_433_eq/radio_433_eq.h
Line
Count
Source (jump to first uncovered line)
1
#ifndef RADIO_SWITCH_H
2
#define RADIO_SWITCH_H
3
#include <gtest/gtest.h>
4
#include <gmock/gmock.h>
5
#include <map>
6
#include "../iDomStatus/idomstatus.h"
7
#include "../433MHz/RFLink/rflinkhandler.h"
8
9
#include "../433MHz/rc_433mhz.h"
10
#include "json.hpp"
11
12
struct WEATHER_STRUCT{
13
private:
14
    unsigned long int m_counter = 0;
15
protected:
16
    unsigned int m_humidity = 0;
17
    double m_temperature = 0.0;
18
    unsigned int m_barometricPressure = 0;
19
public:
20
    unsigned int getHumidity(){ return m_humidity; }
21
    double getTemperature(){ return m_temperature; }
22
    unsigned int getBarometricPressure(){ return m_barometricPressure; }
23
    std::string getDataString(){
24
        return "data: "+std::to_string(m_counter)+"\n"+"Humidity=" + std::to_string(getHumidity()) +"%\n"+
25
                "temperature= " + to_string_with_precision(getTemperature()) + "c\n"+
26
                "Pressure= " + std::to_string(getBarometricPressure())+ "kPa\n";
27
    }
28
29
    void putData(std::string data){
30
        std::string tempStr;
31
        int t = 0;
32
        ++m_counter;
33
        try{
34
            m_humidity = std::stoi( RFLinkHandler::getArgumentValueFromRFLinkMSG(data, "HUM") );
35
        }
36
        catch (...){ }
37
        try{
38
            m_barometricPressure = std::stoi( RFLinkHandler::getArgumentValueFromRFLinkMSG(data, "BARO") );
39
        }
40
        catch (...){ }
41
        try{
42
            tempStr = RFLinkHandler::getArgumentValueFromRFLinkMSG(data, "TEMP");
43
            std::stringstream ss;
44
            ss << std::hex << tempStr.substr(tempStr.size()-3,tempStr.size());
45
            ss >> t;
46
            m_temperature = t / 10.0;
47
            if(tempStr.at(0) == '8'){
48
                m_temperature *= -1.0;
49
            }
50
        }
51
        catch (...){ }
52
        //std::cout << "DUPA: "<<data<<" temp=" << m_temperature<< " hum="<<m_humidity<< std::endl;
53
    }
54
};
55
56
enum class RADIO_EQ_TYPE{
57
    SWITCH = 1,
58
    PIR,
59
    GATE,
60
    BUTTON,
61
    WEATHER_S,
62
    NONE
63
};
64
struct RADIO_EQ_CONFIG{
65
    std::string name = "NULL";
66
    std::string ID   = "NULL";
67
    std::string type = "NULL";
68
    std::string onCode  = "NULL";
69
    std::string offCode = "NULL";
70
    std::string on15sec = "NULL";
71
    std::string sunrise = "NULL";
72
    std::string sunset  = "NULL";
73
    std::string lock   = "NULL";
74
    std::string unlock = "NULL";
75
    void set(std::string type,
76
             std::string name,
77
             std::string ID,
78
             std::string onCode = "null",
79
             std::string offCode = "null",
80
             std::string on15sec = "null",
81
             std::string sunrise = "null",
82
             std::string sunset = "null",
83
             std::string lock = "null",
84
             std::string unlock = "null"){
85
        this->name = name;
86
        this->ID   = ID;
87
        this->type = type;
88
        this->onCode  = onCode;
89
        this->offCode = offCode;
90
        this->on15sec = on15sec;
91
        this->sunrise = sunrise;
92
        this->sunset  = sunset;
93
        this->lock   = lock;
94
        this->unlock = unlock;
95
    }
96
97
    nlohmann::json getJson(){
98
        nlohmann::json jj;
99
        jj["name"]  = name;
100
        jj["id"]    = ID;
101
        jj["type"]  = type;
102
        jj["ON"]    = onCode;
103
        jj["OFF"]   = offCode;
104
        jj["on15sec"] = on15sec;
105
        jj["sunrise"] = sunrise;
106
        jj["sunset"]  = sunset;
107
        jj["lock"]   = lock;
108
        jj["unlock"] = unlock;
109
        return jj;
110
    }
111
};
112
113
class RADIO_EQ{
114
public:
115
    RADIO_EQ();
116
    virtual ~RADIO_EQ();
117
    virtual STATE getState() = 0;
118
    virtual std::string getName() = 0;
119
    virtual std::string getID() = 0;
120
    virtual RADIO_EQ_TYPE getType();
121
protected:
122
    thread_data *m_my_data;
123
    RADIO_EQ_TYPE m_type;
124
public:
125
    RADIO_EQ_CONFIG m_config;
126
};
127
class RADIO_WEATHER_STATION: public RADIO_EQ
128
{
129
    STATE m_state = STATE::UNDEFINE;
130
131
public:
132
    RADIO_WEATHER_STATION(thread_data * my_data, const RADIO_EQ_CONFIG& cfg, RADIO_EQ_TYPE type);
133
    ~RADIO_WEATHER_STATION();
134
    STATE getState();
135
    std::string getName();
136
    std::string getID();
137
    // data
138
    WEATHER_STRUCT data;
139
};
140
class RADIO_BUTTON: public RADIO_EQ
141
{
142
    STATE m_state = STATE::UNDEFINE;
143
144
public:
145
    RADIO_BUTTON(thread_data * my_data, const RADIO_EQ_CONFIG& cfg, RADIO_EQ_TYPE type);
146
    ~RADIO_BUTTON();
147
    STATE getState();
148
    void setState(STATE s);
149
    std::string getName();
150
    std::string getID();
151
};
152
153
class RADIO_SWITCH: public RADIO_EQ
154
{
155
#ifdef BT_TEST
156
public:
157
#endif
158
    RC_433MHz main433MHz;
159
    STATE m_state = STATE::UNDEFINE;
160
public:
161
    RADIO_SWITCH(thread_data * my_data, const RADIO_EQ_CONFIG& cfg, RADIO_EQ_TYPE type);
162
    ~RADIO_SWITCH();
163
    void on();
164
    void off();
165
    void onFor15sec();
166
    void onSunrise();
167
    void onSunset();
168
    void onLockHome();
169
    void onUnlockHome();
170
    STATE getState();
171
    std::string getName();
172
    std::string getID();
173
    void setCode(RADIO_EQ_CONFIG cfg);
174
    STATE m_sunrise = STATE::UNDEFINE;
175
    STATE m_sunset  = STATE::UNDEFINE;
176
};
177
178
class RADIO_EQ_CONTAINER
179
{
180
    std::map <std::string, RADIO_EQ* > m_radioEqMap;
181
    thread_data * my_data;
182
    nlohmann::json m_configJson;
183
public:
184
    RADIO_EQ_CONTAINER(thread_data * my_data);
185
    virtual ~RADIO_EQ_CONTAINER();
186
    void addRadioEq(RADIO_EQ_CONFIG cfg, RADIO_EQ_TYPE type);
187
    void addRadioEq(RADIO_EQ_CONFIG cfg, const std::string& type);
188
    void deleteRadioEq(const std::string &name);
189
    virtual RADIO_EQ* getEqPointer(std::string name);
190
    std::vector<RADIO_SWITCH*> getSwitchPointerVector();
191
    std::vector<RADIO_BUTTON*> getButtonPointerVector();
192
    std::vector<RADIO_WEATHER_STATION *> getWeather_StationPtrVector();
193
    std::string listAllName();
194
    bool nameExist(const std::string &name);
195
    void loadConfig(const std::string &filePath);
196
    void saveConfig(const std::string &filePath);
197
};
198
199
class RADIO_EQ_CONTAINER_STUB : public RADIO_EQ_CONTAINER
200
{
201
    thread_data * k;
202
public:
203
0
    RADIO_EQ_CONTAINER_STUB(thread_data * k):RADIO_EQ_CONTAINER(k){this->k = k;}
204
205
0
    virtual ~RADIO_EQ_CONTAINER_STUB(){puts("~RADIO_EQ_CONTAINER_STUB()");}
206
    MOCK_METHOD1(getEqPointer, RADIO_EQ*(std::string name));
207
};
208
209
#endif // RADIO_SWITCH_H
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/thread_functions/iDom_thread.cpp
Line
Count
Source (jump to first uncovered line)
1
#include "iDom_thread.h"
2
#include "../functions/functions.h"
3
#include <tuple>
4
#include <array>
5
#include <functional>
6
7
std::string iDOM_THREAD::start_thread(const std::string& name,
8
                                      std::function<void(thread_data*,const std::string& threadName)> functionToThread, //void(fn)(thread_data),
9
                                      thread_data* my_data,
10
                                      int thread_socket)
11
5
{
12
5
    int freeSlotID = useful_F::findFreeThreadSlot(my_data->main_THREAD_arr);
13
5
14
5
    if ( freeSlotID != -1)
15
4
    {
16
4
        my_data->main_THREAD_arr->at(freeSlotID).thread = std::thread(functionToThread ,my_data, name);
17
4
18
4
        my_data->main_THREAD_arr->at(freeSlotID).thread_name   = name;
19
4
        my_data->main_THREAD_arr->at(freeSlotID).thread_ID     = my_data->main_THREAD_arr->at(freeSlotID).thread.get_id();
20
4
        my_data->main_THREAD_arr->at(freeSlotID).thread_socket = thread_socket;
21
4
        my_data->main_THREAD_arr->at(freeSlotID).thread.detach();
22
4
23
4
        log_file_mutex.mutex_lock();
24
4
        log_file_cout << INFO << "watek " << name << " wystartowal "<< my_data->main_THREAD_arr->at(freeSlotID).thread_ID << std::endl;
25
4
        log_file_mutex.mutex_unlock();
26
4
27
4
        return "DONE - " + name + " STARTED";
28
4
    }
29
1
    return "not free space to new thread";
30
1
}
31
32
std::string iDOM_THREAD::start_thread_RS232(const std::string &name,
33
                                            std::function<void (thread_data_rs232 *, const std::string &)> functionToThread,
34
                                            thread_data* my_data,
35
                                            thread_data_rs232 *my_data_rs232,
36
                                            int thread_socket)
37
0
{
38
0
    int freeSlotID = useful_F::findFreeThreadSlot(my_data->main_THREAD_arr);
39
0
40
0
    if ( freeSlotID != -1)
41
0
    {
42
0
        my_data->main_THREAD_arr->at(freeSlotID).thread = std::thread(functionToThread ,my_data_rs232, name);
43
0
44
0
        my_data->main_THREAD_arr->at(freeSlotID).thread_name   = name;
45
0
        my_data->main_THREAD_arr->at(freeSlotID).thread_ID     = my_data->main_THREAD_arr->at(freeSlotID).thread.get_id();
46
0
        my_data->main_THREAD_arr->at(freeSlotID).thread_socket = thread_socket;
47
0
        my_data->main_THREAD_arr->at(freeSlotID).thread.detach();
48
0
49
0
        log_file_mutex.mutex_lock();
50
0
        log_file_cout << INFO << "watek " << name << " wystartowal "<< my_data->main_THREAD_arr->at(freeSlotID).thread_ID << std::endl;
51
0
        log_file_mutex.mutex_unlock();
52
0
53
0
        return "DONE - " + name + " STARTED";
54
0
    }
55
0
    return "not free space to new thread";
56
0
}
57
58
void iDOM_THREAD::stop_thread(const std::string& name,
59
                              thread_data* my_data)
60
5
{
61
5
    try
62
5
    {
63
24
        for (int i =0; i< iDomConst::MAX_CONNECTION; ++i)
64
23
        {
65
23
            if (my_data->main_THREAD_arr->at(i).thread_ID == std::this_thread::get_id())
66
4
            {
67
4
                //my_data->main_THREAD_arr[i].thread.detach();
68
4
                my_data->main_THREAD_arr->at(i).thread_name ="  -empty-  ";
69
4
                my_data->main_THREAD_arr->at(i).thread_ID = std::thread::id();
70
4
                my_data->main_THREAD_arr->at(i).thread_socket = 0;
71
4
                break;
72
4
            }
73
23
        }
74
5
    }
75
5
    catch (std::system_error &e)
76
5
    {
77
0
        log_file_mutex.mutex_lock();
78
0
        log_file_cout << ERROR<< "zlapano wyjatek w watku: " << name << ": " << e.what()<< std::endl;
79
0
        log_file_mutex.mutex_unlock();
80
0
    }
81
5
82
5
    log_file_mutex.mutex_lock();
83
5
    log_file_cout << INFO<< "koniec watku: " <<name << std::endl;
84
5
    log_file_mutex.mutex_unlock();
85
5
}
86
87
void iDOM_THREAD::waitUntilAllThreadEnd(thread_data *my_data)
88
0
{
89
0
    int threadCounter = 0;
90
0
    int counter = 20;
91
0
    do{
92
0
        if (--counter == 0){
93
0
            puts("niedoczekalem sie konca watkow");
94
0
            break;
95
0
        }
96
0
        std::this_thread::sleep_for(std::chrono::milliseconds(1500));
97
0
        threadCounter = 0;
98
0
        for(auto i = my_data->main_THREAD_arr->begin(); i < my_data->main_THREAD_arr->end(); ++i)
99
0
        {
100
0
            threadCounter += i->thread_socket;
101
0
            if (i->thread_socket != 0)
102
0
                std::cout << "thread name: "<< i->thread_name << std::endl;
103
0
        }
104
0
        std::cout << "watki pracuja "<<threadCounter<< std::endl;
105
0
    } while(threadCounter != 0);
106
0
}
107
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDomTools/lightning.h
Line
Count
Source
1
#ifndef LIGHTNING_H
2
#define LIGHTNING_H
3
#include <iostream>
4
5
#include "../../libs/Statistic/statistic.h"
6
#include "../../libs/useful/useful.h"
7
8
#include "idomtools_useful.h"
9
#include "json.hpp"
10
11
class CARDINAL_DIRECTIONS{
12
public:
13
    enum class CARDINAL_DIRECTIONS_ENUM{
14
        /*
15
           N
16
        NNW NNE
17
      NW       NE
18
   WNW         ENE
19
 W            E
20
   WSW       ESE
21
      SW     SE
22
        SSW  SSE
23
           S
24
    */
25
26
        N = 1,NNE,NE,ENE,E,ESE,SE,SSE,S,SSW,SW,WSW,W,WNW,NW,NNW,ERROR
27
    };
28
    static CARDINAL_DIRECTIONS_ENUM stringToCardinalDirectionsEnum(std::string s){
29
        if (s == "N")      return CARDINAL_DIRECTIONS_ENUM::N;
30
        else if (s == "NNE")    return CARDINAL_DIRECTIONS_ENUM::NNE;
31
        else if (s == "NE")     return CARDINAL_DIRECTIONS_ENUM::NE;
32
        else if (s == "ENE")    return CARDINAL_DIRECTIONS_ENUM::ENE;
33
        else if (s == "E")      return CARDINAL_DIRECTIONS_ENUM::E;
34
        else if (s == "ESE")    return CARDINAL_DIRECTIONS_ENUM::ESE;
35
        else if (s == "SE")     return CARDINAL_DIRECTIONS_ENUM::SE;
36
        else if (s == "SSE")    return CARDINAL_DIRECTIONS_ENUM::SSE;
37
        else if (s == "S")      return CARDINAL_DIRECTIONS_ENUM::S;
38
        else if (s == "SSW")    return CARDINAL_DIRECTIONS_ENUM::SSW;
39
        else if (s == "SW")     return CARDINAL_DIRECTIONS_ENUM::SW;
40
        else if (s == "WSW")    return CARDINAL_DIRECTIONS_ENUM::WSW;
41
        else if (s == "W")      return CARDINAL_DIRECTIONS_ENUM::W;
42
        else if (s == "WNW")    return CARDINAL_DIRECTIONS_ENUM::WNW;
43
        else if (s == "NW")     return CARDINAL_DIRECTIONS_ENUM::NW;
44
        else if (s == "NNW")    return CARDINAL_DIRECTIONS_ENUM::NNW;
45
        else                    return CARDINAL_DIRECTIONS_ENUM::ERROR;
46
    }
47
48
    static std::string cardinalDirectionsEnumToString(CARDINAL_DIRECTIONS_ENUM e){
49
        switch (e){
50
        case CARDINAL_DIRECTIONS_ENUM::N:
51
            return "N";
52
        case CARDINAL_DIRECTIONS_ENUM::NNE:
53
            return "NNE";
54
        case CARDINAL_DIRECTIONS_ENUM:: NE:
55
            return "NE";
56
        case CARDINAL_DIRECTIONS_ENUM::ENE:
57
            return "ENE";
58
        case CARDINAL_DIRECTIONS_ENUM::E:
59
            return "E";
60
        case CARDINAL_DIRECTIONS_ENUM::ESE:
61
            return "ESE";
62
        case CARDINAL_DIRECTIONS_ENUM::SE:
63
            return "SE";
64
        case CARDINAL_DIRECTIONS_ENUM::SSE:
65
            return "SSE";
66
        case CARDINAL_DIRECTIONS_ENUM::S:
67
            return "S";
68
        case CARDINAL_DIRECTIONS_ENUM::SSW:
69
            return "SSW";
70
        case CARDINAL_DIRECTIONS_ENUM::SW:
71
            return "SW";
72
        case CARDINAL_DIRECTIONS_ENUM::WSW:
73
            return "WSW";
74
        case CARDINAL_DIRECTIONS_ENUM::W:
75
            return "W";
76
        case CARDINAL_DIRECTIONS_ENUM::WNW:
77
            return "WNW";
78
        case CARDINAL_DIRECTIONS_ENUM::NW:
79
            return "NW";
80
        case CARDINAL_DIRECTIONS_ENUM::NNW:
81
            return "NNW";
82
        default:
83
            return "UNKNOWN DIRECTION";
84
        }
85
    }
86
    static std::string cardinalDirectionsEnumToHuman(CARDINAL_DIRECTIONS_ENUM e){
87
        switch (e){
88
        case CARDINAL_DIRECTIONS_ENUM::N:
89
            return "północ";
90
        case CARDINAL_DIRECTIONS_ENUM::NNE:
91
            return "północ - północny wschód";
92
        case CARDINAL_DIRECTIONS_ENUM:: NE:
93
            return "północny wschód";
94
        case CARDINAL_DIRECTIONS_ENUM::ENE:
95
            return "wschód - północny wschód";
96
        case CARDINAL_DIRECTIONS_ENUM::E:
97
            return "wschód";
98
        case CARDINAL_DIRECTIONS_ENUM::ESE:
99
            return "wschód - południowy wschód";
100
        case CARDINAL_DIRECTIONS_ENUM::SE:
101
            return "południowy wschód";
102
        case CARDINAL_DIRECTIONS_ENUM::SSE:
103
            return "południe - południowy wschód";
104
        case CARDINAL_DIRECTIONS_ENUM::S:
105
            return "południe";
106
        case CARDINAL_DIRECTIONS_ENUM::SSW:
107
            return "południe - południowy zachów";
108
        case CARDINAL_DIRECTIONS_ENUM::SW:
109
            return "południowy zachów";
110
        case CARDINAL_DIRECTIONS_ENUM::WSW:
111
            return "zachód - południowy zachów";
112
        case CARDINAL_DIRECTIONS_ENUM::W:
113
            return "zachód";
114
        case CARDINAL_DIRECTIONS_ENUM::WNW:
115
            return "zachód - północny zachód";
116
        case CARDINAL_DIRECTIONS_ENUM::NW:
117
            return "północny zachód";
118
        case CARDINAL_DIRECTIONS_ENUM::NNW:
119
            return "północ - północny zachód";
120
        default:
121
            return "UNKNOWN DIRECTION";
122
        }
123
    }
124
    struct ALARM_INFO{
125
        ALARM_INFO():
126
            riseAlarm(false),
127
            timestamp(0),
128
            distance(0.0),
129
            bearingENG(CARDINAL_DIRECTIONS::CARDINAL_DIRECTIONS_ENUM::ERROR)
130
404
        {
131
404
            data << "NULL";
132
404
        }
133
        ALARM_INFO(const ALARM_INFO &s):
134
            riseAlarm(s.riseAlarm),
135
            data(s.data.str()),
136
            timestamp(s.timestamp),
137
            distance(s.distance),
138
            bearingENG(s.bearingENG)
139
        {
140
        }
141
        ALARM_INFO& operator = (const ALARM_INFO& s)
142
        {
143
            this->data.str(std::string());
144
            this->riseAlarm = s.riseAlarm;
145
            this->data << s.data.str();
146
            this->timestamp = s.timestamp;
147
            this->distance = s.distance;
148
            this->bearingENG = s.bearingENG;
149
            return *this;
150
        }
151
152
        bool riseAlarm;
153
        std::stringstream data;
154
        unsigned int timestamp; //second
155
        double distance; //km
156
        CARDINAL_DIRECTIONS::CARDINAL_DIRECTIONS_ENUM bearingENG;
157
    };
158
};
159
160
class LIGHTNING
161
{
162
public:
163
    LIGHTNING();
164
    ~LIGHTNING();
165
    CARDINAL_DIRECTIONS::ALARM_INFO lightningAlert(nlohmann::json jj);
166
    bool checkLightningAlert(CARDINAL_DIRECTIONS::ALARM_INFO* info);
167
private:
168
    bool alarmState = false;
169
    Clock lightningTime;
170
    double oldDistance = 0.0;
171
};
172
173
#endif // LIGHTNING_H
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/src/thread_functions/rs232_thread.h
Line
Count
Source (jump to first uncovered line)
1
#ifndef RS232_THREAD_H
2
#define RS232_THREAD_H
3
4
#include "../c_connection/c_connection.h"
5
#include "../TASKER/tasker.h"
6
#include "../SerialPi/serialpi.h"
7
#include "../thread_functions/iDom_thread.h"
8
9
//////////// watek wysylajacy/obdbierajacy dane z portu RS232 ////////
10
4
void Send_Recieve_rs232_thread (thread_data_rs232 *data_rs232, const std::string& threadName){
11
4
12
4
    SerialPi serial_ardu(data_rs232->portRS232);
13
4
    serial_ardu.begin( std::stoi( data_rs232->BaudRate));
14
4
15
4
    log_file_mutex.mutex_lock();
16
4
    log_file_cout << INFO <<"otwarcie portu RS232 " << data_rs232->portRS232 << " " <<data_rs232->BaudRate<<std::endl;
17
4
    log_file_mutex.mutex_unlock();
18
4
19
4
    SerialPi serial_ardu_clock(data_rs232->portRS232_clock);
20
4
    serial_ardu_clock.begin( std::stoi( data_rs232->BaudRate));
21
4
22
4
    log_file_mutex.mutex_lock();
23
4
    log_file_cout << INFO <<"otwarcie portu RS232_clock " << data_rs232->portRS232_clock <<" "<< data_rs232->BaudRate <<std::endl;
24
4
    log_file_mutex.mutex_unlock();
25
4
26
4
    /////////////////////////////////////////////////// RESET ARDUINO AFTER RESTART ////////////////////////////////
27
4
    puts("restart arduino\n");
28
4
    //C_connection::mutex_who.lock();
29
4
    {
30
4
        std::lock_guard<std::mutex> lockWho(useful_F::mutex_who);
31
4
        buffer = "reset:00;";
32
4
        serial_ardu.print(buffer.c_str());
33
4
    }
34
4
    //C_connection::mutex_who.unlock();
35
4
    //puts("test testo po lock");
36
4
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
37
4
    while(useful_F::go_while)
38
4
    {
39
4
        std::this_thread::sleep_for( std::chrono::milliseconds(50));
40
4
        //puts("test testo po lock");
41
4
        { //mutex who
42
4
            std::lock_guard<std::mutex> lockWho(useful_F::mutex_who);
43
4
44
4
            if(data_rs232->pointer.ptr_who[0] == iDomConst::RS232)
45
1
            {
46
1
                std::lock_guard<std::mutex> lockBuf(useful_F::mutex_buf);
47
1
                data_rs232->pointer.ptr_who[0] = data_rs232->pointer.ptr_who[1];
48
1
                data_rs232->pointer.ptr_who[1] = iDomConst::RS232;
49
1
                serial_ardu.print(buffer.c_str());
50
1
51
1
                buffer.erase();
52
1
53
3
                while(useful_F::go_while){
54
3
                    if(serial_ardu.available()>0){
55
3
                        buffer += serial_ardu.read();
56
3
                    }
57
3
                    if(buffer[buffer.size()-1] == ';')
58
1
                    {
59
1
                        buffer.erase(buffer.end()-1);
60
1
                        break;
61
1
                    }
62
3
                }
63
1
#ifdef BT_TEST
64
1
                useful_F::go_while = false;
65
1
                return;
66
1
#endif
67
1
            }
68
3
            else if(data_rs232->pointer.ptr_who[0] == iDomConst::CLOCK)
69
2
            {
70
2
                std::lock_guard<std::mutex> lockBuf(useful_F::mutex_buf);
71
2
                data_rs232->pointer.ptr_who[0] = data_rs232->pointer.ptr_who[1];
72
2
                data_rs232->pointer.ptr_who[1] = iDomConst::CLOCK;
73
2
                serial_ardu_clock.print(buffer.c_str());
74
2
75
2
                buffer.erase();
76
2
77
2
                while(useful_F::go_while){
78
2
                    if(serial_ardu_clock.available()>0)
79
1
                    {
80
1
                        buffer += serial_ardu_clock.read();
81
1
                        buffer += serial_ardu_clock.read();
82
1
                        serial_ardu_clock.flush();
83
1
                        break;
84
1
                    }
85
1
                    else
86
1
                    {
87
1
                        puts("w buforze serial_ardu_clock nie ma avaiable ");
88
1
89
1
                        useful_F::myStaticData->myEventHandler.run("RS232")
90
1
                                ->addEvent("w buforze serial_ardu_clock nie ma avaiable ");
91
1
                        break;
92
1
                    }
93
2
                }
94
2
#ifdef BT_TEST
95
2
                useful_F::go_while = false;
96
2
                return;
97
2
#endif
98
2
            }
99
1
            else if(data_rs232->pointer.ptr_who[0] == iDomConst::FREE)
100
1
            {
101
1
                std::string bufor = "";
102
1
                if(serial_ardu.available()>0) {
103
1
104
5
                    while (useful_F::go_while){
105
5
                        // std::cout << "serial_ardu.available(): "<<serial_ardu.available()<<std::endl;
106
5
                        if(serial_ardu.available()>0){
107
5
                            char t = serial_ardu.read();
108
5
                            // std::cout << "t: "<<t<<std::endl;
109
5
                            if(t == ';'){
110
1
                                serial_ardu.flush();
111
1
                                break;
112
1
                            }
113
4
                            else{
114
4
                                bufor.push_back(t);
115
4
                            }
116
5
                        }
117
5
                    }
118
1
                    useful_F::myStaticData->myEventHandler.run("RS232")->addEvent(bufor);
119
1
120
1
                }
121
1
#ifdef BT_TEST
122
1
                useful_F::go_while = false;
123
1
                return;
124
1
#endif
125
1
            }
126
4
127
4
        }
128
4
    }
129
4
    iDOM_THREAD::stop_thread(threadName, useful_F::myStaticData);
130
0
}
131
#endif // RS232_THREAD_H
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/src/iDomTools/test/iDomTools_fixture.h
Line
Count
Source
1
#include <gtest/gtest.h>
2
#include "test_data.h"
3
#include "../idomtools.h"
4
#include "../../src/functions/functions.h"
5
#include "../../RADIO_433_eq/radio_433_eq.h"
6
#include "testJSON.h"
7
8
class iDomTOOLS_ClassTest : public ::testing::Test
9
{
10
public:
11
    TEST_JSON test_Json;
12
    LIGHTNING test_lightning;
13
    CARDINAL_DIRECTIONS::ALARM_INFO test_struct;
14
    thread_data test_my_data;
15
    iDomSTATUS test_status;
16
    config test_server_set;
17
    std::shared_ptr<RADIO_EQ_CONTAINER> test_rec;
18
    iDOM_STATE main_iDomStatus;
19
    ALERT test_alarmTime;
20
    pilot_led test_pilot_led;
21
    MPD_info test_ptr_MPD;
22
23
    /// pointer
24
    iDomTOOLS* test_idomTOOLS;
25
    /////// method
26
    iDomTOOLS_ClassTest()//:test_rec(&test_my_data)
27
193
    {
28
193
        std::cout << "konstruktor testu " <<std::endl;
29
193
    }
30
    void SetUp()
31
192
    {
32
192
        std::cout << "SetUP testu iDomTOOLS_ClassTest" <<std::endl;
33
192
        test_rec = std::make_shared<RADIO_EQ_CONTAINER>(&test_my_data);
34
192
        test_server_set.TS_KEY = "key test";
35
192
        test_server_set.viberSender = "test sender";
36
192
        test_server_set.viberReceiver = {"R1","R2"};
37
192
        test_server_set.saveFilePath = "/mnt/ramdisk/iDomStateTest2.save";
38
192
        test_server_set.radio433MHzConfigFile = "/mnt/ramdisk/433_eq_conf.json";
39
192
        test_rec->loadConfig(test_server_set.radio433MHzConfigFile);
40
192
41
192
        test_my_data.main_REC = test_rec;
42
192
        test_my_data.server_settings = &test_server_set;
43
192
        test_my_data.main_iDomStatus = &test_status;
44
192
        test_my_data.alarmTime = test_alarmTime;
45
192
        test_my_data.idom_all_state = main_iDomStatus;
46
192
        test_my_data.ptr_pilot_led = &test_pilot_led;
47
192
48
192
        test_status.addObject("house");
49
192
50
192
        /////////// create
51
192
        test_idomTOOLS = new iDomTOOLS(&test_my_data);
52
192
53
192
        test_my_data.main_iDomTools = test_idomTOOLS;
54
192
        test_ptr_MPD.volume = 3;
55
192
        test_my_data.ptr_MPD_info = &test_ptr_MPD;
56
192
57
192
        useful_F::myStaticData = &test_my_data;
58
192
    }
59
60
    void TearDown()
61
192
    {
62
192
        delete test_idomTOOLS;
63
192
    }
64
};
65
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/test/iDom_TESTs-CMAKE/main.cpp
Line
Count
Source (jump to first uncovered line)
1
#include <iostream>
2
#include <gtest/gtest.h>
3
#include <gmock/gmock.h>
4
#include <gconv.h>
5
#include <fstream>
6
#include <sstream>
7
#include <test_data.h>
8
#include <../../../../libs/useful/useful.h>
9
#include "../../../../src/SerialPi/serialpi.h"
10
#include "../../../../src/functions/functions.h"
11
12
10
#define log_file_cout f_log //std::cout   zmien f_log na std::cout  i bedzie wypisywac na
13
std::string  _logfile = "/mnt/ramdisk/iDom_log_BT.log";
14
15
Logger log_file_mutex(_logfile);
16
17
18
std::string TEST_DATA::return_send_to_arduino = "-2:-2";
19
std::string TEST_DATA::return_httpPost = "ok.\n";
20
std::string TEST_DATA::return_httpPost_expect = "";
21
std::string TEST_DATA::return_viber_msg = "";
22
std::string TEST_DATA::serial_b = "NULL";
23
std::string TEST_DATA::serial_sended = "NULL";
24
std::string TEST_DATA::LCD_print = "NULL";
25
int TEST_DATA::test_pin = 0;
26
int TEST_DATA::runLinuxCommandReturn = 0;
27
28
unsigned int Clock::m_BT_H = 0;
29
unsigned int Clock::m_BT_M = 0;
30
31
7
void SerialPi_set_recv_msg(const std::string& m){
32
7
    TEST_DATA::serial_b = m;
33
7
}
34
35
10
void SerialPi_set_serial_sended(const std::string& m){
36
10
    TEST_DATA::serial_sended = m;
37
10
}
38
58
SerialPi::SerialPi(const std::string& a):m_serial_port(10){
39
58
    std::cout << "SerialPi() addres: " << a << std::endl;
40
58
}
41
58
SerialPi::~SerialPi(){
42
58
    std::cout << "~SerialPi()" << std::endl;
43
58
}
44
45
10
void SerialPi::print(const std::string& msg){
46
10
    std::cout << "SerialPi::print() msg: " << msg << std::endl;
47
10
    SerialPi_set_serial_sended(msg);
48
10
}
49
50
51
9
void SerialPi::begin(int serialSpeed){
52
9
    std::cout << "SerialPi::int() serialSpeed: " << serialSpeed << std::endl;
53
9
}
54
55
3
void SerialPi::flush(){
56
3
    std::cout << "SerialPi::flush()" << std::endl;
57
3
    TEST_DATA::serial_b.clear();
58
3
}
59
60
15
int SerialPi::available(){
61
15
    std::cout << "SerialPi::available() " << TEST_DATA::serial_b.size() << std::endl;
62
15
    return static_cast<int>(TEST_DATA::serial_b.size());
63
15
}
64
65
39
char SerialPi::read(){
66
39
    char r = TEST_DATA::serial_b.at(0);
67
39
    TEST_DATA::serial_b.erase(0,1);
68
39
    std::cout << "SerialPi::read(): "<<r<< std::endl;
69
39
    return r;
70
39
}
71
72
20
void digitalWrite(int pin, int mode){}
73
74
void setReturnPinState(int i)
75
7
{
76
7
    TEST_DATA::test_pin = i;
77
7
}
78
79
192
viber_API::viber_API(){}
80
192
void viber_API::setAccessToken(const std::string& accessToken){}
81
192
void viber_API::setURL(const std::string& url){}
82
194
void viber_API::setAvatar(const std::string& avatar){}
83
std::string viber_API::sendViberMSG(const std::string& msg,
84
                                    const std::string& receiver,
85
                                    const std::string& senderName,
86
                                    const std::string& accessToken,
87
11
                                    const std::string& url){
88
11
89
11
    std::cout << "sendViberMSG() "<< msg <<" to: "<< receiver << std::endl;
90
11
    TEST_DATA::return_viber_msg = msg;
91
11
    return"{\"message_status\":\"ok\"}";
92
11
}
93
std::string viber_API::sendViberPicture(const std::string& msg,
94
                                        const std::string& image,
95
                                        const std::string& receiver,
96
                                        const std::string& senderName,
97
                                        const std::string& accessToken ,
98
25
                                        const std::string& url){
99
25
    std::cout << "sendViberPicture() "<< msg <<" to: "<< receiver << std::endl;
100
25
    TEST_DATA::return_viber_msg = msg;
101
25
    return"{\"message_status\":\"ok\"}";
102
25
}
103
192
FACEBOOK_API::FACEBOOK_API(){}
104
std::string FACEBOOK_API::postTxtOnWall(const std::string& msg,
105
0
                                        const std::string& accessToken ){return "";}
106
std::string FACEBOOK_API::postPhotoOnWall(const std::string& url,
107
                                          const std::string& msg ,
108
2
                                          const std::string& accessToken ){return "";}
109
192
void FACEBOOK_API::setAccessToken(const std::string& token){}
110
111
34
void LCD_c::set_lcd_STATE(int i){}
112
174
void LCD_c::printString(bool clear, int col, int row, const std::string& str){
113
174
    std::cout << "LCD_c::printString() "<< str << std::endl;
114
174
    TEST_DATA::LCD_print = str;
115
174
}
116
117
15
std::string useful_F_libs::httpPost(const std::string& url, int timeoutSeconds){
118
15
119
15
    std::cout << "url: "<< url << " return "<< TEST_DATA::return_httpPost << "|"<< std::endl;
120
15
    TEST_DATA::return_httpPost_expect = "httpPost";
121
15
    return TEST_DATA::return_httpPost;
122
15
}
123
4
std::string useful_F_libs::httpPost(const std::string& url){
124
4
    CURL *curl;
125
4
    CURLcode res;
126
4
    std::string readBuffer;
127
4
    curl = curl_easy_init();
128
4
129
4
    if(curl) {
130
4
        curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
131
4
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
132
4
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, useful_F_libs::WriteCallback);
133
4
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
134
4
        res = curl_easy_perform(curl);
135
4
        /* Check for errors */
136
4
        if(res != CURLE_OK)
137
0
            fprintf(stderr, "curl_easy_perform() failed: %s\n",
138
0
                    curl_easy_strerror(res));
139
4
140
4
        /* always cleanup */
141
4
        curl_easy_cleanup(curl);
142
4
    }
143
4
    curl_global_cleanup();
144
4
145
4
    return readBuffer;
146
4
}
147
148
7
int digitalRead(int pin){ return TEST_DATA::test_pin; }
149
150
class test_433
151
{
152
public:
153
    std::string config433 = "{ \"BUTTON\": { \"locker\": { \"OFF\": \"NULL\", \"ON\": \"NULL\", \"id\": \"01e7be\", \"name\": \"locker\", \"type\": \"BUTTON\" } }, \"SWITCH\": { \"A\": { \"OFF\": \"10;TriState;0280aa;0;OFF\", \"ON\": \"10;TriState;0280aa;0;ON\", \"id\": \"1444\", \"name\": \"A\", \"on15sec\": \"null\", \"sunrise\": \"NULL\", \"sunset\": \"NULL\",\"lock\": \"null\", \"unlock\": \"null\", \"type\": \"SWITCH\" }, \"ALARM\": { \"OFF\": \"dummyOFF\", \"ON\": \"dummyON\", \"id\": \"1223\", \"name\": \"ALARM\", \"on15sec\": \"null\", \"sunrise\": \"NULL\", \"sunset\": \"NULL\",\"lock\": \"null\", \"unlock\": \"null\", \"type\": \"SWITCH\" }, \"B\": { \"OFF\": \"10;TriState;02822a;0;OFF\", \"ON\": \"10;TriState;02822a;0;ON\", \"id\": \"1445\", \"name\": \"B\", \"on15sec\": \"null\", \"sunrise\": \"ON\", \"sunset\": \"OFF\", \"lock\": \"null\", \"unlock\": \"null\",\"type\": \"SWITCH\" }, \"C\": { \"OFF\": \"10;TriState;02828a;0;OFF\", \"ON\": \"10;TriState;02828a;0;ON\", \"id\": \"1446\", \"name\": \"C\", \"on15sec\": \"null\", \"sunrise\": \"OFF\", \"sunset\": \"ON\", \"lock\": \"null\", \"unlock\": \"null\",\"type\": \"SWITCH\" }, \"listwa\": { \"OFF\": \"10;Kaku;0ad04d;15;OFF\", \"ON\": \"10;Kaku;0ad04d;15;ON\", \"id\": \"1450\", \"name\": \"listwa\", \"on15sec\": \"null\", \"sunrise\": \"NULL\", \"sunset\": \"NULL\",\"lock\": \"OFF\", \"unlock\": \"ON\", \"type\": \"SWITCH\" } }, \"WEATHER\": { \"first\": { \"OFF\": \"NULL\", \"ON\": \"NULL\", \"id\": \"0704\", \"name\": \"first\", \"on15sec\": \"null\", \"sunrise\": \"NULL\", \"sunset\": \"NULL\", \"type\": \"WEATHER\" } } }";
154
    std::string config433_fake = "{ \"BUTTON\": { \"locker\": { \"OFF\": \"NULL\", \"ON\": \"NULL\", \"id\": \"01e7be\", \"name\": \"locker\",  \"type\": \"BUTTON\" } }, \"SWITCH\": { \"A\": { \"OFF\": \"10;TriState;0280aa;0;OFF\", \"ON\": \"10;TriState;0280aa;0;ON\", \"id\": \"1444\", \"name\": \"A\", \"on15sec\": \"null\", \"sunrise\": \"NULL\", \"sunset\": \"NULL\",\"lock\": \"null\", \"unlock\": \"null\", \"type\": \"SWITCH\" }, \"ALARM\": { \"OFF\": \"dummyOFF\", \"ON\": \"dummyON\", \"id\": \"1223\", \"name\": \"ALARM\", \"on15sec\": \"null\", \"sunrise\": \"NULL\", \"sunset\": \"NULL\",\"lock\": \"null\", \"unlock\": \"null\", \"type\": \"SWITCH\" }, \"B\": { \"OFF\": \"10;TriState;02822a;0;OFF\", \"ON\": \"10;TriState;02822a;0;ON\", \"id\": \"1445\", \"name\": \"B\", \"on15sec\": \"null\", \"sunrise\": \"NULL\", \"sunset\": \"NULL\", \"lock\": \"null\", \"unlock\": \"null\",\"type\": \"SWITCH\" }, \"C\": { \"OFF\": \"10;TriState;02828a;0;OFF\", \"ON\": \"10;TriState;02828a;0;ON\", \"id\": \"1446\", \"name\": \"C\", \"on15sec\": \"null\", \"sunrise\": \"NULL\", \"sunset\": \"NULL\",\"lock\": \"null\", \"unlock\": \"null\", \"type\": \"SWITCH\" }, \"listwa\": { \"OFF\": \"10;Kaku;0ad04d;15;OFF\", \"ON\": \"10;Kaku;0ad04d;15;ON\", \"id\": \"1450\", \"name\": \"listwa\", \"on15sec\": \"null\", \"sunrise\": \"NULL\", \"sunset\": \"NULL\",\"lock\": \"OFF\", \"unlock\": \"null\", \"type\": \"SWITCH\" } } } }";
155
156
    void makeFile(const std::string& path)
157
1
    {
158
1
        std::ofstream o(path);
159
1
        o << config433 ;
160
1
    }
161
    void makeFileFake(const std::string& path)
162
1
    {
163
1
        std::ofstream o(path);
164
1
        o << config433_fake ;
165
1
    }
166
};
167
168
int main(int argc, char **argv)
169
1
{
170
1
    test_433 t;
171
1
    t.makeFile("/mnt/ramdisk/433_eq_conf.json");
172
1
    t.makeFileFake("/mnt/ramdisk/433_eq_conf_fake.json");
173
1
174
1
    std::fstream ofs;
175
1
    ofs.open(_logfile, std::ios::out | std::ios::trunc);
176
1
    ofs.close(); //Using microsoft incremental linker version 14
177
1
178
1
    pthread_mutex_init(&Logger::mutex_log, NULL);
179
1
180
1
    log_file_mutex.mutex_lock();
181
1
    log_file_cout << std::endl<< std::endl<<"============================================"
182
1
                  << std::endl<< std::endl<< std::endl<< INFO << "START BT "<< std::endl;
183
1
    log_file_mutex.mutex_unlock();
184
1
185
1
    ::testing::InitGoogleTest( &argc, argv );
186
1
    //::testing::GTEST_FLAG(filter) = "functions_fixture.sleepThread";
187
1
    //::testing::GTEST_FLAG(filter) = "event_counter_fixture.getLast1minNumberEvent";
188
1
    //::testing::GTEST_FLAG(filter) = "command433MHz_Class_fixture.*)";
189
1
    auto ret = RUN_ALL_TESTS();
190
1
    pthread_mutex_destroy(&Logger::mutex_log);
191
1
192
1
    const char * PROG_INFO =  " Basic TEST iDomServer: " __DATE__ ", " __TIME__;
193
1
    std::cout << "wersja " <<PROG_INFO <<" "<< GIT_BRANCH <<" " << GIT_COMMIT_HASH << std::endl;
194
1
    return ret;
195
1
}
/mnt/c/cyniu/PROGRAMOWANIE/malina/iDom_server_OOP/test/iDom_TESTs-CMAKE/main.cpp
Line
Count
Source (jump to first uncovered line)
1
#include <iostream>
2
#include <gtest/gtest.h>
3
#include <gmock/gmock.h>
4
#include <gconv.h>
5
#include <fstream>
6
#include <sstream>
7
#include <test_data.h>
8
#include <../../../../libs/useful/useful.h>
9
#include "../../../../src/SerialPi/serialpi.h"
10
#include "../../../../src/functions/functions.h"
11
12
10
#define log_file_cout f_log //std::cout   zmien f_log na std::cout  i bedzie wypisywac na
13
std::string  _logfile = "/mnt/ramdisk/iDom_log_BT.log";
14
15
Logger log_file_mutex(_logfile);
16
17
18
std::string TEST_DATA::return_send_to_arduino = "-2:-2";
19
std::string TEST_DATA::return_httpPost = "ok.\n";
20
std::string TEST_DATA::return_httpPost_expect = "";
21
std::string TEST_DATA::return_viber_msg = "";
22
std::string TEST_DATA::serial_b = "NULL";
23
std::string TEST_DATA::serial_sended = "NULL";
24
std::string TEST_DATA::LCD_print = "NULL";
25
int TEST_DATA::test_pin = 0;
26
int TEST_DATA::runLinuxCommandReturn = 0;
27
28
unsigned int Clock::m_BT_H = 0;
29
unsigned int Clock::m_BT_M = 0;
30
31
7
void SerialPi_set_recv_msg(const std::string& m){
32
7
    TEST_DATA::serial_b = m;
33
7
}
34
35
10
void SerialPi_set_serial_sended(const std::string& m){
36
10
    TEST_DATA::serial_sended = m;
37
10
}
38
58
SerialPi::SerialPi(const std::string& a):m_serial_port(10){
39
58
    std::cout << "SerialPi() addres: " << a << std::endl;
40
58
}
41
58
SerialPi::~SerialPi(){
42
58
    std::cout << "~SerialPi()" << std::endl;
43
58
}
44
45
10
void SerialPi::print(const std::string& msg){
46
10
    std::cout << "SerialPi::print() msg: " << msg << std::endl;
47
10
    SerialPi_set_serial_sended(msg);
48
10
}
49
50
51
9
void SerialPi::begin(int serialSpeed){
52
9
    std::cout << "SerialPi::int() serialSpeed: " << serialSpeed << std::endl;
53
9
}
54
55
3
void SerialPi::flush(){
56
3
    std::cout << "SerialPi::flush()" << std::endl;
57
3
    TEST_DATA::serial_b.clear();
58
3
}
59
60
15
int SerialPi::available(){
61
15
    std::cout << "SerialPi::available() " << TEST_DATA::serial_b.size() << std::endl;
62
15
    return static_cast<int>(TEST_DATA::serial_b.size());
63
15
}
64
65
39
char SerialPi::read(){
66
39
    char r = TEST_DATA::serial_b.at(0);
67
39
    TEST_DATA::serial_b.erase(0,1);
68
39
    std::cout << "SerialPi::read(): "<<r<< std::endl;
69
39
    return r;
70
39
}
71
72
20
void digitalWrite(int pin, int mode){}
73
74
void setReturnPinState(int i)
75
7
{
76
7
    TEST_DATA::test_pin = i;
77
7
}
78
79
192
viber_API::viber_API(){}
80
192
void viber_API::setAccessToken(const std::string& accessToken){}
81
192
void viber_API::setURL(const std::string& url){}
82
194
void viber_API::setAvatar(const std::string& avatar){}
83
std::string viber_API::sendViberMSG(const std::string& msg,
84
                                    const std::string& receiver,
85
                                    const std::string& senderName,
86
                                    const std::string& accessToken,
87
11
                                    const std::string& url){
88
11
89
11
    std::cout << "sendViberMSG() "<< msg <<" to: "<< receiver << std::endl;
90
11
    TEST_DATA::return_viber_msg = msg;
91
11
    return"{\"message_status\":\"ok\"}";
92
11
}
93
std::string viber_API::sendViberPicture(const std::string& msg,
94
                                        const std::string& image,
95
                                        const std::string& receiver,
96
                                        const std::string& senderName,
97
                                        const std::string& accessToken ,
98
25
                                        const std::string& url){
99
25
    std::cout << "sendViberPicture() "<< msg <<" to: "<< receiver << std::endl;
100
25
    TEST_DATA::return_viber_msg = msg;
101
25
    return"{\"message_status\":\"ok\"}";
102
25
}
103
192
FACEBOOK_API::FACEBOOK_API(){}
104
std::string FACEBOOK_API::postTxtOnWall(const std::string& msg,
105
0
                                        const std::string& accessToken ){return "";}
106
std::string FACEBOOK_API::postPhotoOnWall(const std::string& url,
107
                                          const std::string& msg ,
108
2
                                          const std::string& accessToken ){return "";}
109
192
void FACEBOOK_API::setAccessToken(const std::string& token){}
110
111
34
void LCD_c::set_lcd_STATE(int i){}
112
174
void LCD_c::printString(bool clear, int col, int row, const std::string& str){
113
174
    std::cout << "LCD_c::printString() "<< str << std::endl;
114
174
    TEST_DATA::LCD_print = str;
115
174
}
116
117
15
std::string useful_F_libs::httpPost(const std::string& url, int timeoutSeconds){
118
15
119
15
    std::cout << "url: "<< url << " return "<< TEST_DATA::return_httpPost << "|"<< std::endl;
120
15
    TEST_DATA::return_httpPost_expect = "httpPost";
121
15
    return TEST_DATA::return_httpPost;
122
15
}
123
4
std::string useful_F_libs::httpPost(const std::string& url){
124
4
    CURL *curl;
125
4
    CURLcode res;
126
4
    std::string readBuffer;
127
4
    curl = curl_easy_init();
128
4
129
4
    if(curl) {
130
4
        curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
131
4
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
132
4
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, useful_F_libs::WriteCallback);
133
4
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
134
4
        res = curl_easy_perform(curl);
135
4
        /* Check for errors */
136
4
        if(res != CURLE_OK)
137
4
            fprintf(stderr, "curl_easy_perform() failed: %s\n",
138
0
                    curl_easy_strerror(res));
139
4
140
4
        /* always cleanup */
141
4
        curl_easy_cleanup(curl);
142
4
    }
143
4
    curl_global_cleanup();
144
4
145
4
    return readBuffer;
146
4
}
147
148
7
int digitalRead(int pin){ return TEST_DATA::test_pin; }
149
150
class test_433
151
{
152
public:
153
    std::string config433 = "{ \"BUTTON\": { \"locker\": { \"OFF\": \"NULL\", \"ON\": \"NULL\", \"id\": \"01e7be\", \"name\": \"locker\", \"type\": \"BUTTON\" } }, \"SWITCH\": { \"A\": { \"OFF\": \"10;TriState;0280aa;0;OFF\", \"ON\": \"10;TriState;0280aa;0;ON\", \"id\": \"1444\", \"name\": \"A\", \"on15sec\": \"null\", \"sunrise\": \"NULL\", \"sunset\": \"NULL\",\"lock\": \"null\", \"unlock\": \"null\", \"type\": \"SWITCH\" }, \"ALARM\": { \"OFF\": \"dummyOFF\", \"ON\": \"dummyON\", \"id\": \"1223\", \"name\": \"ALARM\", \"on15sec\": \"null\", \"sunrise\": \"NULL\", \"sunset\": \"NULL\",\"lock\": \"null\", \"unlock\": \"null\", \"type\": \"SWITCH\" }, \"B\": { \"OFF\": \"10;TriState;02822a;0;OFF\", \"ON\": \"10;TriState;02822a;0;ON\", \"id\": \"1445\", \"name\": \"B\", \"on15sec\": \"null\", \"sunrise\": \"ON\", \"sunset\": \"OFF\", \"lock\": \"null\", \"unlock\": \"null\",\"type\": \"SWITCH\" }, \"C\": { \"OFF\": \"10;TriState;02828a;0;OFF\", \"ON\": \"10;TriState;02828a;0;ON\", \"id\": \"1446\", \"name\": \"C\", \"on15sec\": \"null\", \"sunrise\": \"OFF\", \"sunset\": \"ON\", \"lock\": \"null\", \"unlock\": \"null\",\"type\": \"SWITCH\" }, \"listwa\": { \"OFF\": \"10;Kaku;0ad04d;15;OFF\", \"ON\": \"10;Kaku;0ad04d;15;ON\", \"id\": \"1450\", \"name\": \"listwa\", \"on15sec\": \"null\", \"sunrise\": \"NULL\", \"sunset\": \"NULL\",\"lock\": \"OFF\", \"unlock\": \"ON\", \"type\": \"SWITCH\" } }, \"WEATHER\": { \"first\": { \"OFF\": \"NULL\", \"ON\": \"NULL\", \"id\": \"0704\", \"name\": \"first\", \"on15sec\": \"null\", \"sunrise\": \"NULL\", \"sunset\": \"NULL\", \"type\": \"WEATHER\" } } }";
154
    std::string config433_fake = "{ \"BUTTON\": { \"locker\": { \"OFF\": \"NULL\", \"ON\": \"NULL\", \"id\": \"01e7be\", \"name\": \"locker\",  \"type\": \"BUTTON\" } }, \"SWITCH\": { \"A\": { \"OFF\": \"10;TriState;0280aa;0;OFF\", \"ON\": \"10;TriState;0280aa;0;ON\", \"id\": \"1444\", \"name\": \"A\", \"on15sec\": \"null\", \"sunrise\": \"NULL\", \"sunset\": \"NULL\",\"lock\": \"null\", \"unlock\": \"null\", \"type\": \"SWITCH\" }, \"ALARM\": { \"OFF\": \"dummyOFF\", \"ON\": \"dummyON\", \"id\": \"1223\", \"name\": \"ALARM\", \"on15sec\": \"null\", \"sunrise\": \"NULL\", \"sunset\": \"NULL\",\"lock\": \"null\", \"unlock\": \"null\", \"type\": \"SWITCH\" }, \"B\": { \"OFF\": \"10;TriState;02822a;0;OFF\", \"ON\": \"10;TriState;02822a;0;ON\", \"id\": \"1445\", \"name\": \"B\", \"on15sec\": \"null\", \"sunrise\": \"NULL\", \"sunset\": \"NULL\", \"lock\": \"null\", \"unlock\": \"null\",\"type\": \"SWITCH\" }, \"C\": { \"OFF\": \"10;TriState;02828a;0;OFF\", \"ON\": \"10;TriState;02828a;0;ON\", \"id\": \"1446\", \"name\": \"C\", \"on15sec\": \"null\", \"sunrise\": \"NULL\", \"sunset\": \"NULL\",\"lock\": \"null\", \"unlock\": \"null\", \"type\": \"SWITCH\" }, \"listwa\": { \"OFF\": \"10;Kaku;0ad04d;15;OFF\", \"ON\": \"10;Kaku;0ad04d;15;ON\", \"id\": \"1450\", \"name\": \"listwa\", \"on15sec\": \"null\", \"sunrise\": \"NULL\", \"sunset\": \"NULL\",\"lock\": \"OFF\", \"unlock\": \"null\", \"type\": \"SWITCH\" } } } }";
155
156
    void makeFile(const std::string& path)
157
1
    {
158
1
        std::ofstream o(path);
159
1
        o << config433 ;
160
1
    }
161
    void makeFileFake(const std::string& path)
162
1
    {
163
1
        std::ofstream o(path);
164
1
        o << config433_fake ;
165
1
    }
166
};
167
168
int main(int argc, char **argv)
169
1
{
170
1
    test_433 t;
171
1
    t.makeFile("/mnt/ramdisk/433_eq_conf.json");
172
1
    t.makeFileFake("/mnt/ramdisk/433_eq_conf_fake.json");
173
1
174
1
    std::fstream ofs;
175
1
    ofs.open(_logfile, std::ios::out | std::ios::trunc);
176
1
    ofs.close(); //Using microsoft incremental linker version 14
177
1
178
1
    pthread_mutex_init(&Logger::mutex_log, NULL);
179
1
180
1
    log_file_mutex.mutex_lock();
181
1
    log_file_cout << std::endl<< std::endl<<"============================================"
182
1
                  << std::endl<< std::endl<< std::endl<< INFO << "START BT "<< std::endl;
183
1
    log_file_mutex.mutex_unlock();
184
1
185
1
    ::testing::InitGoogleTest( &argc, argv );
186
1
    //::testing::GTEST_FLAG(filter) = "functions_fixture.sleepThread";
187
1
    //::testing::GTEST_FLAG(filter) = "event_counter_fixture.getLast1minNumberEvent";
188
1
    //::testing::GTEST_FLAG(filter) = "command433MHz_Class_fixture.*)";
189
1
    auto ret = RUN_ALL_TESTS();
190
1
    pthread_mutex_destroy(&Logger::mutex_log);
191
1
192
1
    const char * PROG_INFO =  " Basic TEST iDomServer: " __DATE__ ", " __TIME__;
193
1
    std::cout << "wersja " <<PROG_INFO <<" "<< GIT_BRANCH <<" " << GIT_COMMIT_HASH << std::endl;
194
1
    return ret;
195
1
}
=======
/mnt/e/PROGRAMOWANIE/malina/iDom_server_OOP/test/iDom_TESTs-CMAKE/wiringPi.h
Line
Count
Source
1
12
#define LOW      0
2
8
#define HIGH  1
3
int digitalRead (int pin) ;
4
void digitalWrite (int pin, int value) ;
>>>>>>> 25731884c92dced9f2a8b310690c32a805a5ae35